2006-06-25 20:48:02 -04:00
|
|
|
/*
|
2020-06-04 17:20:13 -04:00
|
|
|
* include/haproxy/server-t.h
|
2011-03-20 05:32:26 -04:00
|
|
|
* This file defines everything related to servers.
|
|
|
|
|
*
|
2012-02-13 11:12:08 -05:00
|
|
|
* Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
|
2011-03-20 05:32:26 -04:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2020-06-04 17:20:13 -04:00
|
|
|
#ifndef _HAPROXY_SERVER_T_H
|
|
|
|
|
#define _HAPROXY_SERVER_T_H
|
2006-06-25 20:48:02 -04:00
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
2021-10-06 12:31:48 -04:00
|
|
|
#include <import/ebtree-t.h>
|
2020-06-04 17:20:13 -04:00
|
|
|
|
2020-06-09 03:07:15 -04:00
|
|
|
#include <haproxy/api-t.h>
|
2020-06-04 12:21:56 -04:00
|
|
|
#include <haproxy/check-t.h>
|
2020-06-04 17:20:13 -04:00
|
|
|
#include <haproxy/connection-t.h>
|
2020-06-04 05:01:17 -04:00
|
|
|
#include <haproxy/counters-t.h>
|
2024-03-26 10:01:35 -04:00
|
|
|
#include <haproxy/guid-t.h>
|
2020-06-04 08:58:24 -04:00
|
|
|
#include <haproxy/listener-t.h>
|
2020-06-04 05:29:21 -04:00
|
|
|
#include <haproxy/obj_type-t.h>
|
2021-06-18 03:30:30 -04:00
|
|
|
#include <haproxy/queue-t.h>
|
2022-09-30 11:44:15 -04:00
|
|
|
#include <haproxy/quic_tp-t.h>
|
2021-02-12 13:42:55 -05:00
|
|
|
#include <haproxy/resolvers-t.h>
|
2020-10-05 05:49:42 -04:00
|
|
|
#include <haproxy/stats-t.h>
|
2020-06-04 11:25:40 -04:00
|
|
|
#include <haproxy/task-t.h>
|
2020-06-04 17:20:13 -04:00
|
|
|
#include <haproxy/thread-t.h>
|
2022-11-17 04:37:58 -05:00
|
|
|
#include <haproxy/event_hdl-t.h>
|
2024-02-23 09:57:21 -05:00
|
|
|
#include <haproxy/log-t.h>
|
2023-11-09 07:45:03 -05:00
|
|
|
#include <haproxy/tools-t.h>
|
2006-06-25 20:48:02 -04:00
|
|
|
|
|
|
|
|
|
2014-12-09 21:21:30 -05:00
|
|
|
/* server states. Only SRV_ST_STOPPED indicates a down server. */
|
2014-05-13 09:54:22 -04:00
|
|
|
enum srv_state {
|
2014-05-13 17:41:20 -04:00
|
|
|
SRV_ST_STOPPED = 0, /* the server is down. Please keep set to zero. */
|
|
|
|
|
SRV_ST_STARTING, /* the server is warming up (up but throttled) */
|
|
|
|
|
SRV_ST_RUNNING, /* the server is fully up */
|
|
|
|
|
SRV_ST_STOPPING, /* the server is up but soft-stopping (eg: 404) */
|
2017-11-26 01:26:48 -05:00
|
|
|
} __attribute__((packed));
|
2014-05-13 13:44:56 -04:00
|
|
|
|
2014-05-22 10:14:34 -04:00
|
|
|
/* Administrative status : a server runs in one of these 3 stats :
|
|
|
|
|
* - READY : normal mode
|
|
|
|
|
* - DRAIN : takes no new visitor, equivalent to weight == 0
|
|
|
|
|
* - MAINT : maintenance mode, no more traffic nor health checks.
|
|
|
|
|
*
|
|
|
|
|
* Each server may be in maintenance by itself or may inherit this status from
|
|
|
|
|
* another server it tracks. It can also be in drain mode by itself or inherit
|
|
|
|
|
* it from another server. Let's store these origins here as flags. These flags
|
|
|
|
|
* are combined this way :
|
|
|
|
|
*
|
|
|
|
|
* FMAINT IMAINT FDRAIN IDRAIN Resulting state
|
|
|
|
|
* 0 0 0 0 READY
|
|
|
|
|
* 0 0 0 1 DRAIN
|
|
|
|
|
* 0 0 1 x DRAIN
|
|
|
|
|
* 0 1 x x MAINT
|
|
|
|
|
* 1 x x x MAINT
|
|
|
|
|
*
|
|
|
|
|
* This can be simplified this way :
|
|
|
|
|
*
|
|
|
|
|
* state_str = (state & MAINT) ? "MAINT" : (state & DRAIN) : "DRAIN" : "READY"
|
2014-05-13 13:44:56 -04:00
|
|
|
*/
|
|
|
|
|
enum srv_admin {
|
2015-08-08 09:49:13 -04:00
|
|
|
SRV_ADMF_FMAINT = 0x01, /* the server was explicitly forced into maintenance */
|
|
|
|
|
SRV_ADMF_IMAINT = 0x02, /* the server has inherited the maintenance status from a tracked server */
|
2024-09-27 12:38:35 -04:00
|
|
|
SRV_ADMF_CMAINT = 0x04, /* the server is in maintenance because of the configuration (separate) */
|
2015-08-08 09:49:13 -04:00
|
|
|
SRV_ADMF_FDRAIN = 0x08, /* the server was explicitly forced into drain state */
|
|
|
|
|
SRV_ADMF_IDRAIN = 0x10, /* the server has inherited the drain status from a tracked server */
|
|
|
|
|
SRV_ADMF_DRAIN = 0x18, /* mask to check if any drain flag is present */
|
2016-11-02 16:31:27 -04:00
|
|
|
SRV_ADMF_RMAINT = 0x20, /* the server is down because of an IP address resolution failure */
|
2024-09-27 12:38:35 -04:00
|
|
|
|
BUG/MEDIUM: server: server stuck in maintenance after FQDN change
Pierre Bonnat reported that SRV-based server-template recently stopped
to work properly.
After reviewing the changes, it was found that the regression was caused
by a4d04c6 ("BUG/MINOR: server: make sure the HMAINT state is part of MAINT")
Indeed, HMAINT is not a regular maintenance flag. It was implemented in
b418c122 a4d04c6 ("BUG/MINOR: server: make sure the HMAINT state is part
of MAINT"). This flag is only set (and never removed) when the server FQDN
is changed from its initial config-time value. This can happen with "set
server fqdn" command as well as SRV records updates from the DNS. This
flag should ideally belong to server flags.. but it was stored under
srv_admin enum because cur_admin is properly exported/imported via server
state-file while regular server's flags are not.
Due to a4d04c6, when a server FQDN changes, the server is considered in
maintenance, and since the HMAINT flag is never removed, the server is
stuck in maintenance.
To fix the issue, we partially revert a4d04c6. But this latter commit is
right on one point: HMAINT flag was way too confusing and mixed-up between
regular MAINT flags, thus there's nothing to blame about a4d04c6 as it was
error-prone anyway.. To prevent such kind of bugs from happening again,
let's rename HMAINT to something more explicit (SRV_ADMF_FQDN_CHANGED) and
make it stand out under srv_admin enum so we're not tempted to mix it with
regular maintenance flags anymore.
Since a4d04c6 was set to be backported in all versions, this patch must
be backported there as well.
2024-10-16 04:57:32 -04:00
|
|
|
SRV_ADMF_MAINT = 0x23, /* mask to check if any maintenance flag except CMAINT is present */
|
|
|
|
|
|
|
|
|
|
SRV_ADMF_FQDN_CHANGED = 0x40, /* Special value: set (and never removed) if the server fqdn has
|
|
|
|
|
* changed (from cli or resolvers) since its initial value from
|
|
|
|
|
* config. This flag is exported and restored through state-file
|
|
|
|
|
*/
|
2017-11-26 01:26:48 -05:00
|
|
|
} __attribute__((packed));
|
2014-05-13 09:54:22 -04:00
|
|
|
|
2016-09-21 14:26:16 -04:00
|
|
|
/* options for servers' "init-addr" parameter
|
|
|
|
|
* this parameter may be used to drive HAProxy's behavior when parsing a server
|
|
|
|
|
* address at start up time.
|
|
|
|
|
* These values are stored as a list into an integer ordered from first to last
|
|
|
|
|
* starting with the lowest to highest bits. SRV_IADDR_END (0) is used to
|
|
|
|
|
* indicate the end of the list. 3 bits are enough to store each value.
|
|
|
|
|
*/
|
|
|
|
|
enum srv_initaddr {
|
|
|
|
|
SRV_IADDR_END = 0, /* end of the list */
|
|
|
|
|
SRV_IADDR_NONE = 1, /* the server won't have any address at start up */
|
|
|
|
|
SRV_IADDR_LIBC = 2, /* address set using the libc DNS resolver */
|
|
|
|
|
SRV_IADDR_LAST = 3, /* we set the IP address found in state-file for this server */
|
2016-11-02 10:05:56 -04:00
|
|
|
SRV_IADDR_IP = 4, /* we set an arbitrary IP address to the server */
|
2017-11-26 01:26:48 -05:00
|
|
|
} __attribute__((packed));
|
2016-09-21 14:26:16 -04:00
|
|
|
|
2024-09-04 18:27:35 -04:00
|
|
|
/* options for servers' "init-state" parameter this parameter may be
|
|
|
|
|
* used to drive HAProxy's behavior when determining a server's status
|
|
|
|
|
* at start up time.
|
|
|
|
|
*/
|
|
|
|
|
enum srv_init_state {
|
|
|
|
|
SRV_INIT_STATE_FULLY_DOWN = 0, /* the server should initially be considered DOWN until it passes all health checks. Please keep set to zero. */
|
|
|
|
|
SRV_INIT_STATE_DOWN, /* the server should initially be considered DOWN until it passes one health check. */
|
|
|
|
|
SRV_INIT_STATE_UP, /* the server should initially be considered UP, but will go DOWN if it fails one health check. */
|
|
|
|
|
SRV_INIT_STATE_FULLY_UP, /* the server should initially be considered UP, but will go DOWN if it fails all health checks. */
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
2015-05-08 17:34:06 -04:00
|
|
|
/* server-state-file version */
|
2021-02-19 06:10:36 -05:00
|
|
|
#define SRV_STATE_FILE_VERSION 1
|
2015-05-08 17:34:06 -04:00
|
|
|
#define SRV_STATE_FILE_VERSION_MIN 1
|
2021-02-19 06:10:36 -05:00
|
|
|
#define SRV_STATE_FILE_VERSION_MAX 1
|
2017-04-26 05:24:02 -04:00
|
|
|
#define SRV_STATE_FILE_FIELD_NAMES \
|
|
|
|
|
"be_id " \
|
|
|
|
|
"be_name " \
|
|
|
|
|
"srv_id " \
|
|
|
|
|
"srv_name " \
|
|
|
|
|
"srv_addr " \
|
|
|
|
|
"srv_op_state " \
|
|
|
|
|
"srv_admin_state " \
|
|
|
|
|
"srv_uweight " \
|
|
|
|
|
"srv_iweight " \
|
|
|
|
|
"srv_time_since_last_change " \
|
|
|
|
|
"srv_check_status " \
|
|
|
|
|
"srv_check_result " \
|
|
|
|
|
"srv_check_health " \
|
|
|
|
|
"srv_check_state " \
|
|
|
|
|
"srv_agent_state " \
|
|
|
|
|
"bk_f_forced_id " \
|
|
|
|
|
"srv_f_forced_id " \
|
2017-08-01 02:47:19 -04:00
|
|
|
"srv_fqdn " \
|
2018-07-02 11:00:54 -04:00
|
|
|
"srv_port " \
|
2020-11-14 13:25:33 -05:00
|
|
|
"srvrecord " \
|
2021-02-03 16:30:06 -05:00
|
|
|
"srv_use_ssl " \
|
2021-02-11 16:51:26 -05:00
|
|
|
"srv_check_port " \
|
|
|
|
|
"srv_check_addr " \
|
|
|
|
|
"srv_agent_addr " \
|
|
|
|
|
"srv_agent_port"
|
2017-04-26 05:24:02 -04:00
|
|
|
|
2021-02-11 16:51:26 -05:00
|
|
|
#define SRV_STATE_FILE_MAX_FIELDS 25
|
2021-02-19 06:10:36 -05:00
|
|
|
#define SRV_STATE_FILE_MIN_FIELDS_VERSION_1 20
|
|
|
|
|
#define SRV_STATE_FILE_MAX_FIELDS_VERSION_1 25
|
2022-05-09 13:06:39 -04:00
|
|
|
#define SRV_STATE_LINE_MAXLEN 2000
|
2015-05-08 17:34:06 -04:00
|
|
|
|
2017-01-23 15:38:57 -05:00
|
|
|
/* server flags -- 32 bits */
|
2014-05-13 09:54:22 -04:00
|
|
|
#define SRV_F_BACKUP 0x0001 /* this server is a backup server */
|
|
|
|
|
#define SRV_F_MAPPORTS 0x0002 /* this server uses mapped ports */
|
|
|
|
|
#define SRV_F_NON_STICK 0x0004 /* never add connections allocated to this server to a stick table */
|
2014-11-17 09:11:45 -05:00
|
|
|
#define SRV_F_USE_NS_FROM_PP 0x0008 /* use namespace associated with connection if present */
|
2015-07-07 16:02:20 -04:00
|
|
|
#define SRV_F_FORCED_ID 0x0010 /* server's ID was forced in the configuration */
|
2023-11-21 05:10:34 -05:00
|
|
|
#define SRV_F_RHTTP 0x0020 /* reverse HTTP server which requires idle connection for transfers */
|
2021-02-03 16:30:09 -05:00
|
|
|
#define SRV_F_AGENTPORT 0x0040 /* this server has a agent port configured */
|
2016-08-11 17:12:18 -04:00
|
|
|
#define SRV_F_AGENTADDR 0x0080 /* this server has a agent addr configured */
|
MINOR: server: Add dynamic session cookies.
This adds a new "dynamic" keyword for the cookie option. If set, a cookie
will be generated for each server (assuming one isn't already provided on
the "server" line), from the IP of the server, the TCP port, and a secret
key provided. To provide the secret key, a new keyword as been added,
"dynamic-cookie-key", for backends.
Example :
backend bk_web
balance roundrobin
dynamic-cookie-key "bla"
cookie WEBSRV insert dynamic
server s1 127.0.0.1:80 check
server s2 192.168.56.1:80 check
This is a first step to be able to dynamically add and remove servers,
without modifying the configuration file, and still have all the load
balancers redirect the traffic to the right server.
Provide a way to generate session cookies, based on the IP address of the
server, the TCP port, and a secret key provided.
2017-03-14 15:01:29 -04:00
|
|
|
#define SRV_F_COOKIESET 0x0100 /* this server has a cookie configured, so don't generate dynamic cookies */
|
2019-05-08 13:48:32 -04:00
|
|
|
#define SRV_F_FASTOPEN 0x0200 /* Use TCP Fast Open to connect to server */
|
2019-05-22 07:44:48 -04:00
|
|
|
#define SRV_F_SOCKS4_PROXY 0x0400 /* this server uses SOCKS4 proxy */
|
2019-06-07 03:40:55 -04:00
|
|
|
#define SRV_F_NO_RESOLUTION 0x0800 /* disable runtime DNS resolution on this server */
|
2021-03-08 11:08:01 -05:00
|
|
|
#define SRV_F_DYNAMIC 0x1000 /* dynamic server instantiated at runtime */
|
2021-08-23 08:03:20 -04:00
|
|
|
#define SRV_F_NON_PURGEABLE 0x2000 /* this server cannot be removed at runtime */
|
2021-12-01 03:50:41 -05:00
|
|
|
#define SRV_F_DEFSRV_USE_SSL 0x4000 /* default-server uses SSL */
|
2023-01-24 08:40:01 -05:00
|
|
|
#define SRV_F_DELETED 0x8000 /* srv is deleted but not yet purged */
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2014-05-08 23:42:08 -04:00
|
|
|
/* configured server options for send-proxy (server->pp_opts) */
|
2018-02-01 09:53:52 -05:00
|
|
|
#define SRV_PP_V1 0x0001 /* proxy protocol version 1 */
|
|
|
|
|
#define SRV_PP_V2 0x0002 /* proxy protocol version 2 */
|
|
|
|
|
#define SRV_PP_V2_SSL 0x0004 /* proxy protocol version 2 with SSL */
|
|
|
|
|
#define SRV_PP_V2_SSL_CN 0x0008 /* proxy protocol version 2 with CN */
|
|
|
|
|
#define SRV_PP_V2_SSL_KEY_ALG 0x0010 /* proxy protocol version 2 with cert key algorithm */
|
|
|
|
|
#define SRV_PP_V2_SSL_SIG_ALG 0x0020 /* proxy protocol version 2 with cert signature algorithm */
|
|
|
|
|
#define SRV_PP_V2_SSL_CIPHER 0x0040 /* proxy protocol version 2 with cipher used */
|
2018-02-01 12:29:59 -05:00
|
|
|
#define SRV_PP_V2_AUTHORITY 0x0080 /* proxy protocol version 2 with authority */
|
2018-02-05 09:26:43 -05:00
|
|
|
#define SRV_PP_V2_CRC32C 0x0100 /* proxy protocol version 2 with crc32c */
|
2020-03-13 07:34:24 -04:00
|
|
|
#define SRV_PP_V2_UNIQUE_ID 0x0200 /* proxy protocol version 2 with unique ID */
|
2014-05-08 23:42:08 -04:00
|
|
|
|
2006-06-25 20:48:02 -04:00
|
|
|
/* function which act on servers need to return various errors */
|
|
|
|
|
#define SRV_STATUS_OK 0 /* everything is OK. */
|
|
|
|
|
#define SRV_STATUS_INTERNAL 1 /* other unrecoverable errors. */
|
|
|
|
|
#define SRV_STATUS_NOSRV 2 /* no server is available */
|
|
|
|
|
#define SRV_STATUS_FULL 3 /* the/all server(s) are saturated */
|
|
|
|
|
#define SRV_STATUS_QUEUED 4 /* the/all server(s) are saturated but the connection was queued */
|
|
|
|
|
|
2007-12-02 05:01:23 -05:00
|
|
|
/* various constants */
|
|
|
|
|
#define SRV_UWGHT_RANGE 256
|
2013-07-21 19:44:53 -04:00
|
|
|
#define SRV_UWGHT_MAX (SRV_UWGHT_RANGE)
|
2007-12-02 05:01:23 -05:00
|
|
|
#define SRV_EWGHT_RANGE (SRV_UWGHT_RANGE * BE_WEIGHT_SCALE)
|
|
|
|
|
#define SRV_EWGHT_MAX (SRV_UWGHT_MAX * BE_WEIGHT_SCALE)
|
|
|
|
|
|
2012-10-05 07:48:26 -04:00
|
|
|
/* server ssl options */
|
2020-06-04 17:20:13 -04:00
|
|
|
#define SRV_SSL_O_NONE 0x0000
|
2012-10-11 09:28:34 -04:00
|
|
|
#define SRV_SSL_O_NO_TLS_TICKETS 0x0100 /* disable session resumption tickets */
|
2020-06-04 17:20:13 -04:00
|
|
|
#define SRV_SSL_O_NO_REUSE 0x200 /* disable session reuse */
|
|
|
|
|
#define SRV_SSL_O_EARLY_DATA 0x400 /* Allow using early data */
|
2012-10-05 07:48:26 -04:00
|
|
|
|
2020-05-29 19:42:45 -04:00
|
|
|
/* log servers ring's protocols options */
|
|
|
|
|
enum srv_log_proto {
|
|
|
|
|
SRV_LOG_PROTO_LEGACY, // messages on TCP separated by LF
|
|
|
|
|
SRV_LOG_PROTO_OCTET_COUNTING, // TCP frames: MSGLEN SP MSG
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-03 11:40:28 -04:00
|
|
|
/* srv administrative change causes */
|
|
|
|
|
enum srv_adm_st_chg_cause {
|
|
|
|
|
SRV_ADM_STCHGC_NONE = 0,
|
|
|
|
|
SRV_ADM_STCHGC_DNS_NOENT, /* entry removed from srv record */
|
|
|
|
|
SRV_ADM_STCHGC_DNS_NOIP, /* no server ip in the srv record */
|
|
|
|
|
SRV_ADM_STCHGC_DNS_NX, /* resolution spent too much time in NX state */
|
|
|
|
|
SRV_ADM_STCHGC_DNS_TIMEOUT, /* resolution timeout */
|
|
|
|
|
SRV_ADM_STCHGC_DNS_REFUSED, /* query refused by dns server */
|
|
|
|
|
SRV_ADM_STCHGC_DNS_UNSPEC, /* unspecified dns error */
|
|
|
|
|
SRV_ADM_STCHGC_STATS_DISABLE, /* legacy disable from the stats */
|
|
|
|
|
SRV_ADM_STCHGC_STATS_STOP /* legacy stop from the stats */
|
|
|
|
|
};
|
|
|
|
|
|
MINOR: server: change srv_op_st_chg_cause storage type
This one is greatly inspired by "MINOR: server: change adm_st_chg_cause storage type".
While looking at current srv_op_st_chg_cause usage, it was clear that
the struct needed some cleanup since some leftovers from asynchronous server
state change updates were left behind and resulted in some useless code
duplication, and making the whole thing harder to maintain.
Two observations were made:
- by tracking down srv_set_{running, stopped, stopping} usage,
we can see that the <reason> argument is always a fixed statically
allocated string.
- check-related state change context (duration, status, code...) is
not used anymore since srv_append_status() directly extracts the
values from the server->check. This is pure legacy from when
the state changes were applied asynchronously.
To prevent code duplication, useless string copies and make the reason/cause
more exportable, we store it as an enum now, and we provide
srv_op_st_chg_cause() function to fetch the related description string.
HEALTH and AGENT causes (check related) are now explicitly identified to
make consumers like srv_append_op_chg_cause() able to fetch checks info
from the server itself if they need to.
2023-04-04 04:17:40 -04:00
|
|
|
/* srv operational change causes */
|
|
|
|
|
enum srv_op_st_chg_cause {
|
|
|
|
|
SRV_OP_STCHGC_NONE = 0,
|
|
|
|
|
SRV_OP_STCHGC_HEALTH, /* changed from a health check */
|
|
|
|
|
SRV_OP_STCHGC_AGENT, /* changed from an agent check */
|
|
|
|
|
SRV_OP_STCHGC_CLI, /* changed from the cli */
|
|
|
|
|
SRV_OP_STCHGC_LUA, /* changed from lua */
|
|
|
|
|
SRV_OP_STCHGC_STATS_WEB, /* changed from the web interface */
|
|
|
|
|
SRV_OP_STCHGC_STATEFILE /* changed from state file */
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-19 23:30:16 -04:00
|
|
|
struct pid_list {
|
|
|
|
|
struct list list;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
struct task *t;
|
|
|
|
|
int status;
|
|
|
|
|
int exited;
|
|
|
|
|
};
|
|
|
|
|
|
MEDIUM: lb-chash: Deterministic node hashes based on server address
Motivation: When services are discovered through DNS resolution, the order in
which DNS records get resolved and assigned to servers is arbitrary. Therefore,
even though two HAProxy instances using chash balancing might agree that a
particular request should go to server3, it is likely the case that they have
assigned different IPs and ports to the server in that slot.
This patch adds a server option, "hash-key <key>" which can be set to "id" (the
existing behaviour, default), "addr", or "addr-port". By deriving the keys for
the chash tree nodes from a server's address and port we ensure that independent
HAProxy instances will agree on routing decisions. If an address is not known
then the key is derived from the server's puid as it was previously.
When adjusting a server's weight, we now check whether the server's hash has
changed. If it has, we have to remove all its nodes first, since the node keys
will also have to change.
2024-02-16 16:00:35 -05:00
|
|
|
/* srv methods of computing chash keys */
|
|
|
|
|
enum srv_hash_key {
|
|
|
|
|
SRV_HASH_KEY_ID = 0, /* derived from server puid */
|
|
|
|
|
SRV_HASH_KEY_ADDR, /* derived from server address */
|
|
|
|
|
SRV_HASH_KEY_ADDR_PORT /* derived from server address and port */
|
|
|
|
|
};
|
|
|
|
|
|
[MEDIUM] backend: implement consistent hashing variation
Consistent hashing provides some interesting advantages over common
hashing. It avoids full redistribution in case of a server failure,
or when expanding the farm. This has a cost however, the hashing is
far from being perfect, as we associate a server to a request by
searching the server with the closest key in a tree. Since servers
appear multiple times based on their weights, it is recommended to
use weights larger than approximately 10-20 in order to smoothen
the distribution a bit.
In some cases, playing with weights will be the only solution to
make a server appear more often and increase chances of being picked,
so stats are very important with consistent hashing.
In order to indicate the type of hashing, use :
hash-type map-based (default, old one)
hash-type consistent (new one)
Consistent hashing can make sense in a cache farm, in order not
to redistribute everyone when a cache changes state. It could also
probably be used for long sessions such as terminal sessions, though
that has not be attempted yet.
More details on this method of hashing here :
http://www.spiteful.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/
2009-10-01 01:52:15 -04:00
|
|
|
/* A tree occurrence is a descriptor of a place in a tree, with a pointer back
|
|
|
|
|
* to the server itself.
|
|
|
|
|
*/
|
|
|
|
|
struct server;
|
|
|
|
|
struct tree_occ {
|
|
|
|
|
struct server *server;
|
|
|
|
|
struct eb32_node node;
|
|
|
|
|
};
|
|
|
|
|
|
2021-03-04 03:45:32 -05:00
|
|
|
/* Each server will have one occurrence of this structure per thread */
|
|
|
|
|
struct srv_per_thread {
|
2021-03-04 04:47:54 -05:00
|
|
|
struct mt_list streams; /* streams using this server (used by "shutdown server sessions") */
|
2021-03-04 03:45:32 -05:00
|
|
|
struct eb_root idle_conns; /* Shareable idle connections */
|
|
|
|
|
struct eb_root safe_conns; /* Safe idle connections */
|
|
|
|
|
struct eb_root avail_conns; /* Connections in use, but with still new streams available */
|
2023-08-21 12:32:29 -04:00
|
|
|
|
|
|
|
|
/* Secondary idle conn storage used in parallel to idle/safe trees.
|
|
|
|
|
* Used to sort them by last usage and purge them in reverse order.
|
|
|
|
|
*/
|
|
|
|
|
struct list idle_conn_list;
|
2021-03-04 03:45:32 -05:00
|
|
|
};
|
|
|
|
|
|
2022-11-21 08:14:06 -05:00
|
|
|
/* Each server will have one occurrence of this structure per thread group */
|
|
|
|
|
struct srv_per_tgroup {
|
|
|
|
|
unsigned int next_takeover; /* thread ID to try to steal connections from next time */
|
|
|
|
|
};
|
|
|
|
|
|
2021-10-18 08:39:57 -04:00
|
|
|
/* Configure the protocol selection for websocket */
|
|
|
|
|
enum __attribute__((__packed__)) srv_ws_mode {
|
|
|
|
|
SRV_WS_AUTO = 0,
|
|
|
|
|
SRV_WS_H1,
|
|
|
|
|
SRV_WS_H2,
|
|
|
|
|
};
|
|
|
|
|
|
2023-10-28 14:51:26 -04:00
|
|
|
/* Server-side TLV list, contains the types of the TLVs that should be sent out.
|
|
|
|
|
* Additionally, it can contain a format string, if specified in the config.
|
|
|
|
|
*/
|
|
|
|
|
struct srv_pp_tlv_list {
|
|
|
|
|
struct list list;
|
2024-02-23 09:57:21 -05:00
|
|
|
struct lf_expr fmt;
|
2023-10-28 14:51:26 -04:00
|
|
|
char *fmt_string;
|
|
|
|
|
unsigned char type;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-04 11:05:57 -04:00
|
|
|
struct proxy;
|
2006-06-25 20:48:02 -04:00
|
|
|
struct server {
|
2021-03-05 05:37:32 -05:00
|
|
|
/* mostly config or admin stuff, doesn't change often */
|
2012-11-11 18:42:33 -05:00
|
|
|
enum obj_type obj_type; /* object type == OBJ_TYPE_SERVER */
|
2024-09-04 18:27:35 -04:00
|
|
|
enum srv_init_state init_state; /* server's initial state among SRV_INIT_STATE */
|
2017-08-31 08:41:55 -04:00
|
|
|
enum srv_state next_state, cur_state; /* server state among SRV_ST_* */
|
|
|
|
|
enum srv_admin next_admin, cur_admin; /* server maintenance status : SRV_ADMF_* */
|
2020-04-27 06:13:06 -04:00
|
|
|
signed char use_ssl; /* ssl enabled (1: on, 0: disabled, -1 forced off) */
|
2021-03-05 05:37:32 -05:00
|
|
|
unsigned int flags; /* server flags (SRV_F_*) */
|
2018-02-05 09:26:43 -05:00
|
|
|
unsigned int pp_opts; /* proxy protocol options (SRV_PP_*) */
|
2024-10-23 12:18:48 -04:00
|
|
|
struct mt_list global_list; /* attach point in the global servers_list */
|
2006-06-25 20:48:02 -04:00
|
|
|
struct server *next;
|
BUG/MINOR: server/del: fix srv->next pointer consistency
We recently discovered a bug which affects dynamic server deletion:
When a server is deleted, it is removed from the "visible" server list.
But as we've seen in previous commit
("MINOR: server: add SRV_F_DELETED flag"), it can still be accessed by
someone who keeps a reference on it (waiting for the final srv_drop()).
Throughout this transient state, server ptr is still valid (may be
dereferenced) and the flag SRV_F_DELETED is set.
However, as the server is not part of server list anymore, we have
an issue: srv->next pointer won't be updated anymore as the only place
where we perform such update is in cli_parse_delete_server() by
iterating over the "visible" server list.
Because of this, we cannot guarantee that a server with the
SRV_F_DELETED flag has a valid 'next' ptr: 'next' could be pointing
to a fully removed (already freed) server.
This problem can be easily demonstrated with server dumping in
the stats:
server list dumping is performed in stats_dump_proxy_to_buffer()
The function can be interrupted and resumed later by design.
ie: output buffer is full: partial dump and finish the dump after
the flush
This is implemented by calling srv_take() on the server being dumped,
and only releasing it when we're done with it using srv_drop().
(drop can be delayed after function resume if buffer is full)
While the function design seems OK, it works with the assumption that
srv->next will still be valid after the function resumes, which is
not true. (especially if multiple servers are being removed in between
the 2 dumping attempts)
In practice, this did not cause any crash yet (at least this was not
reported so far), because server dumping is so fast that it is very
unlikely that multiple server deletions make their way between 2
dumping attempts in most setups. But still, this is a problem that we
need to address because some upcoming work might depend on this
assumption as well and for the moment it is not safe at all.
========================================================================
Here is a quick reproducer:
With this patch, we're creating a large deletion window of 3s as soon
as we reach a server named "t2" while iterating over the list.
This will give us plenty of time to perform multiple deletions before
the function is resumed.
| diff --git a/src/stats.c b/src/stats.c
| index 84a4f9b6e..15e49b4cd 100644
| --- a/src/stats.c
| +++ b/src/stats.c
| @@ -3189,11 +3189,24 @@ int stats_dump_proxy_to_buffer(struct stconn *sc, struct htx *htx,
| * Temporarily increment its refcount to prevent its
| * anticipated cleaning. Call free_server to release it.
| */
| + struct server *orig = ctx->obj2;
| for (; ctx->obj2 != NULL;
| ctx->obj2 = srv_drop(sv)) {
|
| sv = ctx->obj2;
| + printf("sv = %s\n", sv->id);
| srv_take(sv);
| + if (!strcmp("t2", sv->id) && orig == px->srv) {
| + printf("deletion window: 3s\n");
| + thread_idle_now();
| + thread_harmless_now();
| + sleep(3);
| + thread_harmless_end();
| +
| + thread_idle_end();
| +
| + goto full; /* simulate full buffer */
| + }
|
| if (htx) {
| if (htx_almost_full(htx))
| @@ -4353,6 +4366,7 @@ static void http_stats_io_handler(struct appctx *appctx)
| struct channel *res = sc_ic(sc);
| struct htx *req_htx, *res_htx;
|
| + printf("http dump\n");
| /* only proxy stats are available via http */
| ctx->domain = STATS_DOMAIN_PROXY;
|
Ok, we're ready, now we start haproxy with the following conf:
global
stats socket /tmp/ha.sock mode 660 level admin expose-fd listeners thread 1-1
nbthread 2
frontend stats
mode http
bind *:8081 thread 2-2
stats enable
stats uri /
backend farm
server t1 127.0.0.1:1899 disabled
server t2 127.0.0.1:18999 disabled
server t3 127.0.0.1:18998 disabled
server t4 127.0.0.1:18997 disabled
And finally, we execute the following script:
curl localhost:8081/stats&
sleep .2
echo "del server farm/t2" | nc -U /tmp/ha.sock
echo "del server farm/t3" | nc -U /tmp/ha.sock
This should be enough to reveal the issue, I easily manage to
consistently crash haproxy with the following reproducer:
http dump
sv = t1
http dump
sv = t1
sv = t2
deletion window = 3s
[NOTICE] (2940566) : Server deleted.
[NOTICE] (2940566) : Server deleted.
http dump
sv = t2
sv = �����U
[1] 2940566 segmentation fault (core dumped) ./haproxy -f ttt.conf
========================================================================
To fix this, we add prev_deleted mt_list in server struct.
For a given "visible" server, this list will contain the pending
"deleted" servers references that point to it using their 'next' ptr.
This way, whenever this "visible" server is going to be deleted via
cli_parse_delete_server() it will check for servers in its
'prev_deleted' list and update their 'next' pointer so that they no
longer point to it, and then it will push them in its
'next->prev_deleted' list to transfer the update responsibility to the
next 'visible' server (if next != NULL).
Then, following the same logic, the server about to be removed in
cli_parse_delete_server() will push itself as well into its
'next->prev_deleted' list (if next != NULL) so that it may still use its
'next' ptr for the time it is in transient removal state.
In srv_drop(), right before the server is finally freed, we make sure
to remove it from the 'next->prev_deleted' list so that 'next' won't
try to perform the pointers update for this server anymore.
This has to be done atomically to prevent 'next' srv from accessing a
purged server.
As a result:
for a valid server, either deleted or not, 'next' ptr will always
point to a non deleted (ie: visible) server.
With the proposed fix, and several removal combinations (including
unordered cli_parse_delete_server() and srv_drop() calls), I cannot
reproduce the crash anymore.
Example tricky removal sequence that is now properly handled:
sv list: t1,t2,t3,t4,t5,t6
ops:
take(t2)
del(t4)
del(t3)
del(t5)
drop(t3)
drop(t4)
drop(t5)
drop(t2)
2023-02-01 11:22:32 -05:00
|
|
|
struct mt_list prev_deleted; /* deleted servers with 'next' ptr pointing to us */
|
2009-09-23 16:09:24 -04:00
|
|
|
int cklen; /* the len of the cookie, to speed up checks */
|
2008-02-14 14:25:24 -05:00
|
|
|
int rdr_len; /* the length of the redirection prefix */
|
2007-03-25 15:03:01 -04:00
|
|
|
char *cookie; /* the id set in the cookie */
|
2008-02-14 14:25:24 -05:00
|
|
|
char *rdr_pfx; /* the redirection prefix */
|
2007-03-25 15:03:01 -04:00
|
|
|
|
|
|
|
|
struct proxy *proxy; /* the proxy this server belongs to */
|
2023-09-13 05:52:31 -04:00
|
|
|
const struct mux_proto_list *mux_proto; /* the mux to use for all outgoing connections (specified by the "proto" keyword) */
|
2023-11-09 07:45:03 -05:00
|
|
|
struct net_addr_type addr_type; /* server address type (socket and transport hints) */
|
2023-09-13 05:52:31 -04:00
|
|
|
struct log_target *log_target; /* when 'mode log' is enabled, target facility used to transport log messages */
|
2007-03-25 15:03:01 -04:00
|
|
|
unsigned maxconn, minconn; /* max # of active sessions (0 = unlimited), min# for dynamic limit. */
|
2021-03-04 04:47:54 -05:00
|
|
|
struct srv_per_thread *per_thr; /* array of per-thread stuff such as connections lists */
|
2022-11-21 08:14:06 -05:00
|
|
|
struct srv_per_tgroup *per_tgrp; /* array of per-tgroup stuff such as idle conns */
|
2021-03-05 05:37:32 -05:00
|
|
|
unsigned int *curr_idle_thr; /* Current number of orphan idling connections per thread */
|
|
|
|
|
|
2024-05-23 05:14:13 -04:00
|
|
|
char *pool_conn_name;
|
|
|
|
|
struct sample_expr *pool_conn_name_expr;
|
2018-12-14 12:15:36 -05:00
|
|
|
unsigned int pool_purge_delay; /* Delay before starting to purge the idle conns pool */
|
MEDIUM: server: add a new pool-low-conn server setting
The problem with the way idle connections currently work is that it's
easy for a thread to steal all of its siblings' connections, then release
them, then it's done by another one, etc. This happens even more easily
due to scheduling latencies, or merged events inside the same pool loop,
which, when dealing with a fast server responding in sub-millisecond
delays, can really result in one thread being fully at work at a time.
In such a case, we perform a huge amount of takeover() which consumes
CPU and requires quite some locking, sometimes resulting in lower
performance than expected.
In order to fight against this problem, this patch introduces a new server
setting "pool-low-conn", whose purpose is to dictate when it is allowed to
steal connections from a sibling. As long as the number of idle connections
remains at least as high as this value, it is permitted to take over another
connection. When the idle connection count becomes lower, a thread may only
use its own connections or create a new one. By proceeding like this even
with a low number (typically 2*nbthreads), we quickly end up in a situation
where all active threads have a few connections. It then becomes possible
to connect to a server without bothering other threads the vast majority
of the time, while still being able to use these connections when the
number of available FDs becomes low.
We also use this threshold instead of global.nbthread in the connection
release logic, allowing to keep more extra connections if needed.
A test performed with 10000 concurrent HTTP/1 connections, 16 threads
and 210 servers with 1 millisecond of server response time showed the
following numbers:
haproxy 2.1.7: 185000 requests per second
haproxy 2.2: 314000 requests per second
haproxy 2.2 lowconn 32: 352000 requests per second
The takeover rate goes down from 300k/s to 13k/s. The difference is
further amplified as the response time shrinks.
2020-07-01 01:43:51 -04:00
|
|
|
unsigned int low_idle_conns; /* min idle connection count to start picking from other threads */
|
2018-12-10 12:30:32 -05:00
|
|
|
unsigned int max_idle_conns; /* Max number of connection allowed in the orphan connections list */
|
2019-01-23 04:21:49 -05:00
|
|
|
int max_reuse; /* Max number of requests on a same connection */
|
2011-10-31 06:53:20 -04:00
|
|
|
struct task *warmup; /* the task dedicated to the warmup when slowstart is set */
|
2007-03-25 15:03:01 -04:00
|
|
|
|
2013-12-11 09:27:05 -05:00
|
|
|
struct server *track; /* the server we're currently tracking, if any */
|
|
|
|
|
struct server *trackers; /* the list of servers tracking us, if any */
|
|
|
|
|
struct server *tracknext; /* next server tracking <track> in <track>'s trackers list */
|
2008-02-17 19:26:35 -05:00
|
|
|
char *trackit; /* temporary variable to make assignment deferrable */
|
2009-12-15 16:31:24 -05:00
|
|
|
int consecutive_errors_limit; /* number of consecutive errors that triggers an event */
|
|
|
|
|
short observe, onerror; /* observing mode: one of HANA_OBS_*; what to do on error: on of ANA_ONERR_* */
|
2012-05-24 18:28:52 -04:00
|
|
|
short onmarkeddown; /* what to do when marked down: one of HANA_ONMARKEDDOWN_* */
|
|
|
|
|
short onmarkedup; /* what to do when marked up: one of HANA_ONMARKEDUP_* */
|
2007-11-30 11:42:05 -05:00
|
|
|
int slowstart; /* slowstart time in seconds (ms in the conf) */
|
2007-03-25 15:03:01 -04:00
|
|
|
|
|
|
|
|
char *id; /* just for identification */
|
2022-11-17 10:10:35 -05:00
|
|
|
uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */
|
2017-08-31 08:41:55 -04:00
|
|
|
unsigned iweight,uweight, cur_eweight; /* initial weight, user-specified weight, and effective weight */
|
2007-03-25 15:16:40 -04:00
|
|
|
unsigned wscore; /* weight score, used during srv map computation */
|
2017-08-31 08:41:55 -04:00
|
|
|
unsigned next_eweight; /* next pending eweight to commit */
|
2021-01-07 23:35:52 -05:00
|
|
|
unsigned rweight; /* remainder of weight in the current LB tree */
|
2016-10-25 12:49:45 -04:00
|
|
|
unsigned cumulative_weight; /* weight of servers prior to this one in the same group, for chash balancing */
|
2021-03-05 05:37:32 -05:00
|
|
|
int maxqueue; /* maximum number of pending connections allowed */
|
2022-10-17 08:58:19 -04:00
|
|
|
int shard; /* shard (in peers protocol context only) */
|
2023-10-04 04:32:45 -04:00
|
|
|
int log_bufsize; /* implicit ring bufsize (for log server only - in log backend) */
|
2021-03-05 05:37:32 -05:00
|
|
|
|
2021-10-18 08:39:57 -04:00
|
|
|
enum srv_ws_mode ws; /* configure the protocol selection for websocket */
|
|
|
|
|
/* 3 bytes hole here */
|
|
|
|
|
|
2021-08-25 09:34:53 -04:00
|
|
|
uint refcount; /* refcount used to remove a server at runtime */
|
2021-08-02 09:50:00 -04:00
|
|
|
|
2021-03-05 05:37:32 -05:00
|
|
|
/* The elements below may be changed on every single request by any
|
|
|
|
|
* thread, and generally at the same time.
|
|
|
|
|
*/
|
BUG/MAJOR: compiler: relax alignment constraints on certain structures
In github bug #1517, Mike Lothian reported instant crashes on startup
on RHEL8 + gcc-11 that appeared with 2.4 when allocating a proxy.
The analysis brought us down to the THREAD_ALIGN() entries that were
placed inside the "server" struct to avoid false sharing of cache lines.
It turns out that some modern gcc make use of aligned vector operations
to manipulate some fields (e.g. memset() etc) and that these structures
allocated using malloc() are not necessarily aligned, hence the crash.
The compiler is allowed to do that because the structure claims to be
aligned. The problem is in fact that the alignment propagates to other
structures that embed it. While most of these structures are used as
statically allocated variables, some are dynamic and cannot use that.
A deeper analysis showed that struct server does this, propagates to
struct proxy, which propagates to struct spoe_config, all of which
are allocated using malloc/calloc.
A better approach would consist in usins posix_memalign(), but this one
is not available everywhere and will either need to be reimplemented
less efficiently (by always wasting 64 bytes before the area), or a
few functions will have to be specifically written to deal with the
few structures that are dynamically allocated.
But the deeper problem that remains is that it is difficult to track
structure alignment, as there's no available warning to check this.
For the long term we'll probably have to create a macro such as
"struct_malloc()" etc which takes a type and enforces an alignment
based on the one of this type. This also means propagating that to
pools as well, and it's not a tiny task.
For now, let's get rid of the forced alignment in struct server, and
replace it with extra padding. By punching 63-byte holes, we can keep
areas on separate cache lines. Doing so moderately increases the size
of the "server" structure (~+6%) but that's the best short-term option
and it's easily backportable.
This will have to be backported as far as 2.4.
Thanks to Mike for the detailed report.
2022-01-27 09:46:19 -05:00
|
|
|
THREAD_PAD(63);
|
2021-03-05 05:37:32 -05:00
|
|
|
struct eb32_node idle_node; /* When to next do cleanup in the idle connections */
|
|
|
|
|
unsigned int curr_idle_conns; /* Current number of orphan idling connections, both the idle and the safe lists */
|
|
|
|
|
unsigned int curr_idle_nb; /* Current number of connections in the idle list */
|
|
|
|
|
unsigned int curr_safe_nb; /* Current number of connections in the safe list */
|
|
|
|
|
unsigned int curr_used_conns; /* Current number of used connections */
|
|
|
|
|
unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */
|
|
|
|
|
unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */
|
|
|
|
|
|
2021-06-18 03:30:30 -04:00
|
|
|
struct queue queue; /* pending connections */
|
2024-03-12 09:09:55 -04:00
|
|
|
struct mt_list sess_conns; /* list of private conns managed by a session on this server */
|
BUG/MEDIUM: queue: implement a flag to check for the dequeuing
As unveiled in GH issue #2711, commit 5541d4995d ("BUG/MEDIUM: queue:
deal with a rare TOCTOU in assign_server_and_queue()") does have some
side effects in that it can occasionally cause an endless loop.
As Christopher analysed it, the problem is that process_srv_queue(),
which uses a trylock in order to leave only one thread in charge of
the dequeueing process, can lose the lock race against pendconn_add().
If this happens on the last served request, then there's no more thread
to deal with the dequeuing, and assign_server_and_queue() will loop
forever on a condition that was initially exepected to be extremely
rare (and still is, except that now it can become sticky). Previously
what was happening is that such queued requests would just time out
and since that was very rare, nobody would notice.
The root of the problem really is that trylock. It was added so that
only one thread dequeues at a time but it doesn't offer only that
guarantee since it also prevents a thread from dequeuing if another
one is in the process of queuing. We need a different criterion.
What we're doing now is to set a flag "dequeuing" in the server, which
indicates that one thread is currently in the process of dequeuing
requests. This one is atomically tested, and only if no thread is in
this process, then the thread grabs the queue's lock and dequeues.
This way it will be serialized with pendconn_add() and no request
addition will be missed.
It is not certain whether the original race covered by the fix above
can still happen with this change, so better keep that fix for now.
Thanks to @Yenya (Jan Kasprzak) for the precise and complete report
allowing to spot the problem.
This patch should be backported wherever the patch above was backported.
2024-09-11 03:37:53 -04:00
|
|
|
unsigned int dequeuing; /* non-zero = dequeuing in progress (atomic) */
|
2021-03-05 05:37:32 -05:00
|
|
|
|
|
|
|
|
/* Element below are usd by LB algorithms and must be doable in
|
|
|
|
|
* parallel to other threads reusing connections above.
|
|
|
|
|
*/
|
BUG/MAJOR: compiler: relax alignment constraints on certain structures
In github bug #1517, Mike Lothian reported instant crashes on startup
on RHEL8 + gcc-11 that appeared with 2.4 when allocating a proxy.
The analysis brought us down to the THREAD_ALIGN() entries that were
placed inside the "server" struct to avoid false sharing of cache lines.
It turns out that some modern gcc make use of aligned vector operations
to manipulate some fields (e.g. memset() etc) and that these structures
allocated using malloc() are not necessarily aligned, hence the crash.
The compiler is allowed to do that because the structure claims to be
aligned. The problem is in fact that the alignment propagates to other
structures that embed it. While most of these structures are used as
statically allocated variables, some are dynamic and cannot use that.
A deeper analysis showed that struct server does this, propagates to
struct proxy, which propagates to struct spoe_config, all of which
are allocated using malloc/calloc.
A better approach would consist in usins posix_memalign(), but this one
is not available everywhere and will either need to be reimplemented
less efficiently (by always wasting 64 bytes before the area), or a
few functions will have to be specifically written to deal with the
few structures that are dynamically allocated.
But the deeper problem that remains is that it is difficult to track
structure alignment, as there's no available warning to check this.
For the long term we'll probably have to create a macro such as
"struct_malloc()" etc which takes a type and enforces an alignment
based on the one of this type. This also means propagating that to
pools as well, and it's not a tiny task.
For now, let's get rid of the forced alignment in struct server, and
replace it with extra padding. By punching 63-byte holes, we can keep
areas on separate cache lines. Doing so moderately increases the size
of the "server" structure (~+6%) but that's the best short-term option
and it's easily backportable.
This will have to be backported as far as 2.4.
Thanks to Mike for the detailed report.
2022-01-27 09:46:19 -05:00
|
|
|
THREAD_PAD(63);
|
2021-03-05 05:37:32 -05:00
|
|
|
__decl_thread(HA_SPINLOCK_T lock); /* may enclose the proxy's lock, must not be taken under */
|
|
|
|
|
unsigned npos, lpos; /* next and last positions in the LB tree, protected by LB lock */
|
2023-09-13 05:52:31 -04:00
|
|
|
union {
|
|
|
|
|
struct eb32_node lb_node; /* node used for tree-based load balancing */
|
|
|
|
|
struct list lb_list; /* elem used for list-based load balancing */
|
|
|
|
|
};
|
2007-11-25 19:15:43 -05:00
|
|
|
struct server *next_full; /* next server in the temporary full list */
|
2021-03-05 05:37:32 -05:00
|
|
|
|
|
|
|
|
/* usually atomically updated by any thread during parsing or on end of request */
|
BUG/MAJOR: compiler: relax alignment constraints on certain structures
In github bug #1517, Mike Lothian reported instant crashes on startup
on RHEL8 + gcc-11 that appeared with 2.4 when allocating a proxy.
The analysis brought us down to the THREAD_ALIGN() entries that were
placed inside the "server" struct to avoid false sharing of cache lines.
It turns out that some modern gcc make use of aligned vector operations
to manipulate some fields (e.g. memset() etc) and that these structures
allocated using malloc() are not necessarily aligned, hence the crash.
The compiler is allowed to do that because the structure claims to be
aligned. The problem is in fact that the alignment propagates to other
structures that embed it. While most of these structures are used as
statically allocated variables, some are dynamic and cannot use that.
A deeper analysis showed that struct server does this, propagates to
struct proxy, which propagates to struct spoe_config, all of which
are allocated using malloc/calloc.
A better approach would consist in usins posix_memalign(), but this one
is not available everywhere and will either need to be reimplemented
less efficiently (by always wasting 64 bytes before the area), or a
few functions will have to be specifically written to deal with the
few structures that are dynamically allocated.
But the deeper problem that remains is that it is difficult to track
structure alignment, as there's no available warning to check this.
For the long term we'll probably have to create a macro such as
"struct_malloc()" etc which takes a type and enforces an alignment
based on the one of this type. This also means propagating that to
pools as well, and it's not a tiny task.
For now, let's get rid of the forced alignment in struct server, and
replace it with extra padding. By punching 63-byte holes, we can keep
areas on separate cache lines. Doing so moderately increases the size
of the "server" structure (~+6%) but that's the best short-term option
and it's easily backportable.
This will have to be backported as far as 2.4.
Thanks to Mike for the detailed report.
2022-01-27 09:46:19 -05:00
|
|
|
THREAD_PAD(63);
|
2021-03-05 05:37:32 -05:00
|
|
|
int cur_sess; /* number of currently active sessions (including syn_sent) */
|
|
|
|
|
int served; /* # of active sessions currently being served (ie not pending) */
|
|
|
|
|
int consecutive_errors; /* current number of consecutive errors */
|
|
|
|
|
struct be_counters counters; /* statistics counters */
|
|
|
|
|
|
|
|
|
|
/* Below are some relatively stable settings, only changed under the lock */
|
BUG/MAJOR: compiler: relax alignment constraints on certain structures
In github bug #1517, Mike Lothian reported instant crashes on startup
on RHEL8 + gcc-11 that appeared with 2.4 when allocating a proxy.
The analysis brought us down to the THREAD_ALIGN() entries that were
placed inside the "server" struct to avoid false sharing of cache lines.
It turns out that some modern gcc make use of aligned vector operations
to manipulate some fields (e.g. memset() etc) and that these structures
allocated using malloc() are not necessarily aligned, hence the crash.
The compiler is allowed to do that because the structure claims to be
aligned. The problem is in fact that the alignment propagates to other
structures that embed it. While most of these structures are used as
statically allocated variables, some are dynamic and cannot use that.
A deeper analysis showed that struct server does this, propagates to
struct proxy, which propagates to struct spoe_config, all of which
are allocated using malloc/calloc.
A better approach would consist in usins posix_memalign(), but this one
is not available everywhere and will either need to be reimplemented
less efficiently (by always wasting 64 bytes before the area), or a
few functions will have to be specifically written to deal with the
few structures that are dynamically allocated.
But the deeper problem that remains is that it is difficult to track
structure alignment, as there's no available warning to check this.
For the long term we'll probably have to create a macro such as
"struct_malloc()" etc which takes a type and enforces an alignment
based on the one of this type. This also means propagating that to
pools as well, and it's not a tiny task.
For now, let's get rid of the forced alignment in struct server, and
replace it with extra padding. By punching 63-byte holes, we can keep
areas on separate cache lines. Doing so moderately increases the size
of the "server" structure (~+6%) but that's the best short-term option
and it's easily backportable.
This will have to be backported as far as 2.4.
Thanks to Mike for the detailed report.
2022-01-27 09:46:19 -05:00
|
|
|
THREAD_PAD(63);
|
2021-03-05 05:37:32 -05:00
|
|
|
|
|
|
|
|
struct eb_root *lb_tree; /* we want to know in what tree the server is */
|
|
|
|
|
struct tree_occ *lb_nodes; /* lb_nodes_tot * struct tree_occ */
|
[MEDIUM] backend: implement consistent hashing variation
Consistent hashing provides some interesting advantages over common
hashing. It avoids full redistribution in case of a server failure,
or when expanding the farm. This has a cost however, the hashing is
far from being perfect, as we associate a server to a request by
searching the server with the closest key in a tree. Since servers
appear multiple times based on their weights, it is recommended to
use weights larger than approximately 10-20 in order to smoothen
the distribution a bit.
In some cases, playing with weights will be the only solution to
make a server appear more often and increase chances of being picked,
so stats are very important with consistent hashing.
In order to indicate the type of hashing, use :
hash-type map-based (default, old one)
hash-type consistent (new one)
Consistent hashing can make sense in a cache farm, in order not
to redistribute everyone when a cache changes state. It could also
probably be used for long sessions such as terminal sessions, though
that has not be attempted yet.
More details on this method of hashing here :
http://www.spiteful.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/
2009-10-01 01:52:15 -04:00
|
|
|
unsigned lb_nodes_tot; /* number of allocated lb_nodes (C-HASH) */
|
|
|
|
|
unsigned lb_nodes_now; /* number of lb_nodes placed in the tree (C-HASH) */
|
MEDIUM: lb-chash: Deterministic node hashes based on server address
Motivation: When services are discovered through DNS resolution, the order in
which DNS records get resolved and assigned to servers is arbitrary. Therefore,
even though two HAProxy instances using chash balancing might agree that a
particular request should go to server3, it is likely the case that they have
assigned different IPs and ports to the server in that slot.
This patch adds a server option, "hash-key <key>" which can be set to "id" (the
existing behaviour, default), "addr", or "addr-port". By deriving the keys for
the chash tree nodes from a server's address and port we ensure that independent
HAProxy instances will agree on routing decisions. If an address is not known
then the key is derived from the server's puid as it was previously.
When adjusting a server's weight, we now check whether the server's hash has
changed. If it has, we have to remove all its nodes first, since the node keys
will also have to change.
2024-02-16 16:00:35 -05:00
|
|
|
enum srv_hash_key hash_key; /* method to compute node hash (C-HASH) */
|
|
|
|
|
unsigned lb_server_key; /* hash of the values indicated by "hash_key" (C-HASH) */
|
2007-03-25 15:03:01 -04:00
|
|
|
|
2014-11-17 09:11:45 -05:00
|
|
|
const struct netns_entry *netns; /* contains network namespace name or NULL. Network namespace comes from configuration */
|
REORG: connection: rename the data layer the "transport layer"
While working on the changes required to make the health checks use the
new connections, it started to become obvious that some naming was not
logical at all in the connections. Specifically, it is not logical to
call the "data layer" the layer which is in charge for all the handshake
and which does not yet provide a data layer once established until a
session has allocated all the required buffers.
In fact, it's more a transport layer, which makes much more sense. The
transport layer offers a medium on which data can transit, and it offers
the functions to move these data when the upper layer requests this. And
it is the upper layer which iterates over the transport layer's functions
to move data which should be called the data layer.
The use case where it's obvious is with embryonic sessions : an incoming
SSL connection is accepted. Only the connection is allocated, not the
buffers nor stream interface, etc... The connection handles the SSL
handshake by itself. Once this handshake is complete, we can't use the
data functions because the buffers and stream interface are not there
yet. Hence we have to first call a specific function to complete the
session initialization, after which we'll be able to use the data
functions. This clearly proves that SSL here is only a transport layer
and that the stream interface constitutes the data layer.
A similar change will be performed to rename app_cb => data, but the
two could not be in the same commit for obvious reasons.
2012-10-02 18:19:48 -04:00
|
|
|
struct xprt_ops *xprt; /* transport-layer operations */
|
2024-08-26 05:50:25 -04:00
|
|
|
int alt_proto; /* alternate protocol to use in protocol_lookup */
|
2017-11-26 01:26:48 -05:00
|
|
|
unsigned int svc_port; /* the port to connect to (for relevant families) */
|
[MEDIUM] stats: report server and backend cumulated downtime
Hello,
This patch implements new statistics for SLA calculation by adding new
field 'Dwntime' with total down time since restart (both HTTP/CSV) and
extending status field (HTTP) or inserting a new one (CSV) with time
showing how long each server/backend is in a current state. Additionaly,
down transations are also calculated and displayed for backends, so it is
possible to know how many times selected backend was down, generating "No
server is available to handle this request." error.
New information are presentetd in two different ways:
- for HTTP: a "human redable form", one of "100000d 23h", "23h 59m" or
"59m 59s"
- for CSV: seconds
I believe that seconds resolution is enough.
As there are more columns in the status page I decided to shrink some
names to make more space:
- Weight -> Wght
- Check -> Chk
- Down -> Dwn
Making described changes I also made some improvements and fixed some
small bugs:
- don't increment s->health above 's->rise + s->fall - 1'. Previously it
was incremented an then (re)set to 's->rise + s->fall - 1'.
- do not set server down if it is down already
- do not set server up if it is up already
- fix colspan in multiple places (mostly introduced by my previous patch)
- add missing "status" header to CSV
- fix order of retries/redispatches in server (CSV)
- s/Tthen/Then/
- s/server/backend/ in DATA_ST_PX_BE (dumpstats.c)
Changes from previous version:
- deal with negative time intervales
- don't relay on s->state (SRV_RUNNING)
- little reworked human_time + compacted format (no spaces). If needed it
can be used in the future for other purposes by optionally making "cnt"
as an argument
- leave set_server_down mostly unchanged
- only little reworked "process_chk: 9"
- additional fields in CSV are appended to the rigth
- fix "SEC" macro
- named arguments (human_time, be_downtime, srv_downtime)
Hope it is OK. If there are only cosmetic changes needed please fill free
to correct it, however if there are some bigger changes required I would
like to discuss it first or at last to know what exactly was changed
especially since I already put this patch into my production server. :)
Thank you,
Best regards,
Krzysztof Oledzki
2007-10-22 10:21:10 -04:00
|
|
|
unsigned down_time; /* total time the server was down */
|
|
|
|
|
|
2012-02-13 11:12:08 -05:00
|
|
|
int puid; /* proxy-unique server ID, used for SNMP, and "first" LB algo */
|
2015-10-13 10:16:41 -04:00
|
|
|
int tcp_ut; /* for TCP, user timeout */
|
2009-10-04 08:52:57 -04:00
|
|
|
|
2017-03-14 06:20:13 -04:00
|
|
|
int do_check; /* temporary variable used during parsing to denote if health checks must be enabled */
|
2017-03-21 11:39:15 -04:00
|
|
|
int do_agent; /* temporary variable used during parsing to denote if an auxiliary agent check must be enabled */
|
2013-02-22 20:16:43 -05:00
|
|
|
struct check check; /* health-check specific configuration */
|
2013-11-24 20:46:36 -05:00
|
|
|
struct check agent; /* agent specific configuration */
|
[MEDIUM] checks: support multi-packet health check responses
We are seeing both real servers repeatedly going on- and off-line with
a period of tens of seconds. Packet tracing, stracing, and adding
debug code to HAProxy itself has revealed that the real servers are
always responding correctly, but HAProxy is sometimes receiving only
part of the response.
It appears that the real servers are sending the test page as three
separate packets. HAProxy receives the contents of one, two, or three
packets, apparently randomly. Naturally, the health check only
succeeds when all three packets' data are seen by HAProxy. If HAProxy
and the real servers are modified to use a plain HTML page for the
health check, the response is in the form of a single packet and the
checks do not fail.
(...)
I've added buffer and length variables to struct server, and allocated
space with the rest of the server initialisation.
(...)
It seems to be working fine in my tests, and handles check responses
that are bigger than the buffer.
2010-03-16 11:50:46 -04:00
|
|
|
|
2020-12-23 11:41:43 -05:00
|
|
|
struct resolv_requester *resolv_requester; /* used to link a server to its DNS resolution */
|
2015-04-13 19:15:08 -04:00
|
|
|
char *resolvers_id; /* resolvers section used by this server */
|
2020-12-23 10:51:12 -05:00
|
|
|
struct resolvers *resolvers; /* pointer to the resolvers structure used by this server */
|
2016-11-02 10:34:05 -04:00
|
|
|
char *lastaddr; /* the address string provided by the server-state file */
|
2020-12-23 12:01:04 -05:00
|
|
|
struct resolv_options resolv_opts;
|
2020-07-05 07:36:08 -04:00
|
|
|
int hostname_dn_len; /* string length of the server hostname in Domain Name format */
|
2017-11-26 01:26:48 -05:00
|
|
|
char *hostname_dn; /* server hostname in Domain Name format */
|
|
|
|
|
char *hostname; /* server hostname */
|
2016-11-02 10:05:56 -04:00
|
|
|
struct sockaddr_storage init_addr; /* plain IP address specified on the init-addr line */
|
2016-09-21 14:26:16 -04:00
|
|
|
unsigned int init_addr_methods; /* initial address setting, 3-bit per method, ends at 0, enough to store 10 entries */
|
2023-09-13 05:52:31 -04:00
|
|
|
enum srv_log_proto log_proto; /* used proto to emit messages on server lines from log or ring section */
|
2015-04-13 19:15:08 -04:00
|
|
|
|
2017-03-20 09:54:41 -04:00
|
|
|
char *sni_expr; /* Temporary variable to store a sample expression for SNI */
|
2012-05-18 09:46:21 -04:00
|
|
|
struct {
|
2021-10-06 05:23:32 -04:00
|
|
|
void *ctx;
|
2017-11-16 11:42:52 -05:00
|
|
|
struct {
|
2023-08-21 02:41:49 -04:00
|
|
|
/* ptr/size may be shared R/O with other threads under read lock
|
|
|
|
|
* "sess_lock", however only the owning thread may change them
|
|
|
|
|
* (under write lock).
|
|
|
|
|
*/
|
2017-11-16 11:42:52 -05:00
|
|
|
unsigned char *ptr;
|
|
|
|
|
int size;
|
|
|
|
|
int allocated_size;
|
2021-11-16 20:59:21 -05:00
|
|
|
char *sni; /* SNI used for the session */
|
2023-08-21 02:41:49 -04:00
|
|
|
__decl_thread(HA_RWLOCK_T sess_lock);
|
2017-11-16 11:42:52 -05:00
|
|
|
} * reused_sess;
|
2023-08-21 05:55:42 -04:00
|
|
|
uint last_ssl_sess_tid; /* last tid+1 having updated reused_sess (0=none, >0=tid+1) */
|
2021-01-25 11:19:43 -05:00
|
|
|
|
|
|
|
|
struct ckch_inst *inst; /* Instance of the ckch_store in which the certificate was loaded (might be null if server has no certificate) */
|
2021-02-08 04:43:44 -05:00
|
|
|
__decl_thread(HA_RWLOCK_T lock); /* lock the cache and SSL_CTX during commit operations */
|
2021-01-25 11:19:43 -05:00
|
|
|
|
2012-09-03 17:34:19 -04:00
|
|
|
char *ciphers; /* cipher suite to use if non-null */
|
2018-09-14 05:14:21 -04:00
|
|
|
char *ciphersuites; /* TLS 1.3 cipher suite to use if non-null */
|
2023-09-07 17:13:15 -04:00
|
|
|
char *curves; /* TLS curves list */
|
2012-10-05 07:48:26 -04:00
|
|
|
int options; /* ssl options */
|
2012-10-11 10:11:36 -04:00
|
|
|
int verify; /* verify method (set of SSL_VERIFY_* flags) */
|
2017-11-26 01:26:48 -05:00
|
|
|
struct tls_version_filter methods; /* ssl methods */
|
2013-06-27 03:05:25 -04:00
|
|
|
char *verify_host; /* hostname of certificate must match this host */
|
2012-10-11 10:11:36 -04:00
|
|
|
char *ca_file; /* CAfile to use on verify */
|
|
|
|
|
char *crl_file; /* CRLfile to use on verify */
|
2021-12-28 12:47:17 -05:00
|
|
|
char *client_crt; /* client certificate to send */
|
2023-06-29 07:29:59 -04:00
|
|
|
char *sigalgs; /* Signature algorithms */
|
2023-06-29 08:11:46 -04:00
|
|
|
char *client_sigalgs; /* Client Signature algorithms */
|
2015-07-09 05:40:25 -04:00
|
|
|
struct sample_expr *sni; /* sample expression for SNI */
|
2018-11-20 17:33:50 -05:00
|
|
|
char *npn_str; /* NPN protocol string */
|
|
|
|
|
int npn_len; /* NPN protocol string length */
|
|
|
|
|
char *alpn_str; /* ALPN protocol string */
|
|
|
|
|
int alpn_len; /* ALPN protocol string length */
|
2012-05-18 09:46:21 -04:00
|
|
|
} ssl_ctx;
|
2020-12-23 11:41:43 -05:00
|
|
|
struct resolv_srvrq *srvrq; /* Pointer representing the DNS SRV requeest, if any */
|
2021-06-11 04:48:45 -04:00
|
|
|
struct list srv_rec_item; /* to attach server to a srv record item */
|
2021-06-11 04:08:05 -04:00
|
|
|
struct list ip_rec_item; /* to attach server to a A or AAAA record item */
|
2021-06-11 04:48:45 -04:00
|
|
|
struct ebpt_node host_dn; /* hostdn store for srvrq and state file matching*/
|
2023-10-28 14:51:26 -04:00
|
|
|
struct list pp_tlvs; /* to send out PROXY protocol v2 TLVs */
|
2021-06-15 10:17:17 -04:00
|
|
|
struct task *srvrq_check; /* Task testing SRV record expiration date for this server */
|
2009-10-04 14:54:54 -04:00
|
|
|
struct {
|
|
|
|
|
const char *file; /* file where the section appears */
|
2009-10-04 17:04:08 -04:00
|
|
|
struct eb32_node id; /* place in the tree of used IDs */
|
2019-05-17 08:29:15 -04:00
|
|
|
struct ebpt_node name; /* place in the tree of used names */
|
2017-11-26 01:26:48 -05:00
|
|
|
int line; /* line where the section appears */
|
2009-10-04 14:54:54 -04:00
|
|
|
} conf; /* config information */
|
2020-11-20 03:28:26 -05:00
|
|
|
struct ebpt_node addr_node; /* Node for string representation of address for the server (including port number) */
|
2017-04-13 12:24:23 -04:00
|
|
|
/* Template information used only for server objects which
|
|
|
|
|
* serve as template filled at parsing time and used during
|
|
|
|
|
* server allocations from server templates.
|
|
|
|
|
*/
|
|
|
|
|
struct {
|
|
|
|
|
char *prefix;
|
|
|
|
|
int nb_low;
|
|
|
|
|
int nb_high;
|
|
|
|
|
} tmpl_info;
|
2019-05-22 07:44:48 -04:00
|
|
|
|
2022-11-17 04:37:58 -05:00
|
|
|
event_hdl_sub_list e_subs; /* event_hdl: server's subscribers list (atomically updated) */
|
|
|
|
|
|
2024-03-26 10:01:35 -04:00
|
|
|
struct guid_node guid; /* GUID global tree node */
|
|
|
|
|
|
2021-03-05 05:37:32 -05:00
|
|
|
/* warning, these structs are huge, keep them at the bottom */
|
|
|
|
|
struct conn_src conn_src; /* connection source settings */
|
|
|
|
|
struct sockaddr_storage addr; /* the address to connect to, doesn't include the port */
|
2019-05-22 07:44:48 -04:00
|
|
|
struct sockaddr_storage socks4_addr; /* the address of the SOCKS4 Proxy, including the port */
|
2020-10-05 05:49:42 -04:00
|
|
|
|
|
|
|
|
EXTRA_COUNTERS(extra_counters);
|
2006-06-25 20:48:02 -04:00
|
|
|
};
|
|
|
|
|
|
2022-11-17 04:37:58 -05:00
|
|
|
/* data provided to EVENT_HDL_SUB_SERVER handlers through event_hdl facility */
|
|
|
|
|
struct event_hdl_cb_data_server {
|
|
|
|
|
/* provided by:
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_ADD
|
2023-03-23 09:39:51 -04:00
|
|
|
* EVENT_HDL_SUB_SERVER_DEL
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_UP
|
2022-11-17 04:37:58 -05:00
|
|
|
* EVENT_HDL_SUB_SERVER_DOWN
|
2023-04-04 15:28:07 -04:00
|
|
|
* EVENT_HDL_SUB_SERVER_STATE
|
2023-04-21 12:06:58 -04:00
|
|
|
* EVENT_HDL_SUB_SERVER_ADMIN
|
2023-03-30 04:19:08 -04:00
|
|
|
* EVENT_HDL_SUB_SERVER_CHECK
|
2023-11-10 14:12:00 -05:00
|
|
|
* EVENT_HDL_SUB_SERVER_INETADDR
|
2022-11-17 04:37:58 -05:00
|
|
|
*/
|
|
|
|
|
struct {
|
|
|
|
|
/* safe data can be safely used from both
|
|
|
|
|
* sync and async handlers
|
|
|
|
|
* data consistency is guaranteed
|
|
|
|
|
*/
|
|
|
|
|
char name[64]; /* server name/id */
|
|
|
|
|
char proxy_name[64]; /* id of proxy the server belongs to */
|
2023-03-22 12:35:47 -04:00
|
|
|
int proxy_uuid; /* uuid of the proxy the server belongs to */
|
2022-11-17 04:37:58 -05:00
|
|
|
int puid; /* proxy-unique server ID */
|
2023-02-22 03:26:41 -05:00
|
|
|
uint32_t rid; /* server id revision */
|
2022-11-17 04:37:58 -05:00
|
|
|
unsigned int flags; /* server flags */
|
|
|
|
|
} safe;
|
|
|
|
|
struct {
|
|
|
|
|
/* unsafe data may only be used from sync handlers:
|
|
|
|
|
* in async mode, data consistency cannot be guaranteed
|
|
|
|
|
* and unsafe data may already be stale, thus using
|
|
|
|
|
* it is highly discouraged because it
|
|
|
|
|
* could lead to undefined behavior (UAF, null dereference...)
|
|
|
|
|
*/
|
|
|
|
|
struct server *ptr; /* server live ptr */
|
|
|
|
|
/* lock hints */
|
|
|
|
|
uint8_t thread_isolate; /* 1 = thread_isolate is on, no locking required */
|
2022-11-25 12:07:49 -05:00
|
|
|
uint8_t srv_lock; /* 1 = srv lock is held */
|
2022-11-17 04:37:58 -05:00
|
|
|
} unsafe;
|
|
|
|
|
};
|
2019-06-13 07:24:29 -04:00
|
|
|
|
2023-04-04 15:28:07 -04:00
|
|
|
/* check result snapshot provided through some event_hdl server events */
|
|
|
|
|
struct event_hdl_cb_data_server_checkres {
|
|
|
|
|
uint8_t agent; /* 1 = agent check, 0 = health check */
|
|
|
|
|
enum chk_result result; /* failed, passed, condpass (CHK_RES_*) */
|
|
|
|
|
long duration; /* total check duration in ms */
|
|
|
|
|
struct {
|
|
|
|
|
short status; /* check status as in check->status */
|
|
|
|
|
short code; /* provided with some check statuses */
|
|
|
|
|
} reason;
|
|
|
|
|
struct {
|
|
|
|
|
int cur; /* dynamic (= check->health) */
|
2023-11-21 13:54:16 -05:00
|
|
|
int rise, fall; /* config dependent */
|
2023-04-04 15:28:07 -04:00
|
|
|
} health; /* check's health, see check-t.h */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* data provided to EVENT_HDL_SUB_SERVER_STATE handlers through
|
|
|
|
|
* event_hdl facility
|
|
|
|
|
*
|
|
|
|
|
* Note that this may be casted to regular event_hdl_cb_data_server if
|
|
|
|
|
* you don't care about state related optional info
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server_state {
|
|
|
|
|
/* provided by:
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_STATE
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server server; /* must be at the beginning */
|
|
|
|
|
struct {
|
|
|
|
|
uint8_t type; /* 0 = operational, 1 = administrative */
|
|
|
|
|
enum srv_state old_state, new_state; /* updated by both operational and admin changes */
|
|
|
|
|
uint32_t requeued; /* requeued connections due to server state change */
|
|
|
|
|
union {
|
|
|
|
|
/* state change cause:
|
|
|
|
|
*
|
|
|
|
|
* look for op_st_chg for operational state change,
|
|
|
|
|
* and adm_st_chg for administrative state change
|
|
|
|
|
*/
|
|
|
|
|
struct {
|
|
|
|
|
enum srv_op_st_chg_cause cause;
|
|
|
|
|
union {
|
|
|
|
|
/* check result is provided with
|
|
|
|
|
* cause == SRV_OP_STCHGC_HEALTH or cause == SRV_OP_STCHGC_AGENT
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server_checkres check;
|
|
|
|
|
};
|
|
|
|
|
} op_st_chg;
|
|
|
|
|
struct {
|
|
|
|
|
enum srv_adm_st_chg_cause cause;
|
|
|
|
|
} adm_st_chg;
|
|
|
|
|
};
|
|
|
|
|
} safe;
|
|
|
|
|
/* no unsafe data */
|
|
|
|
|
};
|
|
|
|
|
|
2023-04-21 12:06:58 -04:00
|
|
|
/* data provided to EVENT_HDL_SUB_SERVER_ADMIN handlers through
|
|
|
|
|
* event_hdl facility
|
|
|
|
|
*
|
|
|
|
|
* Note that this may be casted to regular event_hdl_cb_data_server if
|
|
|
|
|
* you don't care about admin related optional info
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server_admin {
|
|
|
|
|
/* provided by:
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_ADMIN
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server server; /* must be at the beginning */
|
|
|
|
|
struct {
|
|
|
|
|
enum srv_admin old_admin, new_admin;
|
|
|
|
|
uint32_t requeued; /* requeued connections due to server admin change */
|
|
|
|
|
/* admin change cause */
|
|
|
|
|
enum srv_adm_st_chg_cause cause;
|
|
|
|
|
} safe;
|
|
|
|
|
/* no unsafe data */
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-30 04:19:08 -04:00
|
|
|
/* data provided to EVENT_HDL_SUB_SERVER_CHECK handlers through
|
|
|
|
|
* event_hdl facility
|
|
|
|
|
*
|
|
|
|
|
* Note that this may be casted to regular event_hdl_cb_data_server if
|
|
|
|
|
* you don't care about check related optional info
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server_check {
|
|
|
|
|
/* provided by:
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_CHECK
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server server; /* must be at the beginning */
|
|
|
|
|
struct {
|
|
|
|
|
struct event_hdl_cb_data_server_checkres res; /* check result snapshot */
|
|
|
|
|
} safe;
|
|
|
|
|
struct {
|
|
|
|
|
struct check *ptr; /* check ptr */
|
|
|
|
|
} unsafe;
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-07 10:18:39 -05:00
|
|
|
/* struct to store server address and port information in INET
|
|
|
|
|
* context
|
|
|
|
|
*/
|
|
|
|
|
struct server_inetaddr {
|
|
|
|
|
int family; /* AF_UNSPEC, AF_INET or AF_INET6 */
|
|
|
|
|
union {
|
|
|
|
|
struct in_addr v4;
|
|
|
|
|
struct in6_addr v6;
|
|
|
|
|
} addr; /* may hold v4 or v6 addr */
|
2023-12-07 11:08:08 -05:00
|
|
|
struct {
|
|
|
|
|
unsigned int svc;
|
|
|
|
|
uint8_t map; /* is a mapped port? (boolean) */
|
|
|
|
|
} port;
|
2023-12-07 10:18:39 -05:00
|
|
|
};
|
|
|
|
|
|
2023-12-29 14:05:20 -05:00
|
|
|
/* struct to store information about server's addr / port updater in
|
2023-12-11 09:06:43 -05:00
|
|
|
* INET context
|
|
|
|
|
*/
|
|
|
|
|
enum server_inetaddr_updater_by {
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_NONE = 0,
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_CLI,
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_LUA,
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_DNS_AR,
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_DNS_CACHE,
|
|
|
|
|
SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER,
|
|
|
|
|
/* changes here must be reflected in SERVER_INETADDR_UPDATER_*
|
|
|
|
|
* helper macros and in server_inetaddr_updater_by_to_str() func
|
|
|
|
|
*/
|
|
|
|
|
};
|
|
|
|
|
struct server_inetaddr_updater {
|
|
|
|
|
enum server_inetaddr_updater_by by; // by identifier (unique)
|
2023-12-12 05:00:10 -05:00
|
|
|
uint8_t dns; // is dns involved?
|
2023-12-11 09:06:43 -05:00
|
|
|
union {
|
|
|
|
|
struct {
|
|
|
|
|
unsigned int ns_id; // nameserver id responsible for the update
|
|
|
|
|
} dns_resolver; // SERVER_INETADDR_UPDATER_DNS_RESOLVER specific infos
|
2024-03-25 08:38:36 -04:00
|
|
|
} u; // per updater's additional ctx
|
2023-12-11 09:06:43 -05:00
|
|
|
};
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_NONE \
|
2023-12-12 05:00:10 -05:00
|
|
|
(struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_NONE, \
|
|
|
|
|
.dns = 0 }
|
2023-12-11 09:06:43 -05:00
|
|
|
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_CLI \
|
2023-12-12 05:00:10 -05:00
|
|
|
(struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_CLI, \
|
|
|
|
|
.dns = 0 }
|
2023-12-11 09:06:43 -05:00
|
|
|
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_LUA \
|
2023-12-12 05:00:10 -05:00
|
|
|
(struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_LUA, \
|
|
|
|
|
.dns = 0 }
|
2023-12-11 09:06:43 -05:00
|
|
|
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_DNS_AR \
|
2023-12-12 05:00:10 -05:00
|
|
|
(struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_DNS_AR, \
|
|
|
|
|
.dns = 1 }
|
2023-12-11 09:06:43 -05:00
|
|
|
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_DNS_CACHE \
|
2023-12-12 05:00:10 -05:00
|
|
|
(struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_DNS_CACHE, \
|
|
|
|
|
.dns = 1 }
|
2023-12-11 09:06:43 -05:00
|
|
|
|
|
|
|
|
#define SERVER_INETADDR_UPDATER_DNS_RESOLVER(_ns_id) \
|
|
|
|
|
(struct server_inetaddr_updater){ \
|
|
|
|
|
.by = SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER, \
|
2023-12-12 05:00:10 -05:00
|
|
|
.dns = 1, \
|
2024-03-25 08:38:36 -04:00
|
|
|
.u.dns_resolver.ns_id = _ns_id, \
|
2023-12-11 09:06:43 -05:00
|
|
|
}
|
|
|
|
|
|
2023-11-10 14:12:00 -05:00
|
|
|
/* data provided to EVENT_HDL_SUB_SERVER_INETADDR handlers through
|
|
|
|
|
* event_hdl facility
|
|
|
|
|
*
|
|
|
|
|
* Note that this may be casted to regular event_hdl_cb_data_server if
|
|
|
|
|
* you don't care about inetaddr related optional info
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server_inetaddr {
|
|
|
|
|
/* provided by:
|
|
|
|
|
* EVENT_HDL_SUB_SERVER_INETADDR
|
|
|
|
|
*/
|
|
|
|
|
struct event_hdl_cb_data_server server; /* must be at the beginning */
|
|
|
|
|
struct {
|
2023-12-07 10:18:39 -05:00
|
|
|
struct server_inetaddr prev;
|
|
|
|
|
struct server_inetaddr next;
|
2023-12-11 11:14:24 -05:00
|
|
|
struct server_inetaddr_updater updater;
|
2023-11-10 14:12:00 -05:00
|
|
|
} safe;
|
|
|
|
|
/* no unsafe data */
|
|
|
|
|
};
|
|
|
|
|
|
2019-06-13 07:24:29 -04:00
|
|
|
/* Storage structure to load server-state lines from a flat file into
|
|
|
|
|
* an ebtree, for faster processing
|
|
|
|
|
*/
|
2021-02-15 11:09:33 -05:00
|
|
|
struct server_state_line {
|
2019-06-13 07:24:29 -04:00
|
|
|
char *line;
|
2021-02-15 12:27:35 -05:00
|
|
|
char *params[SRV_STATE_FILE_MAX_FIELDS];
|
|
|
|
|
struct eb64_node node;
|
2019-06-13 07:24:29 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2012-10-10 02:27:36 -04:00
|
|
|
/* Descriptor for a "server" keyword. The ->parse() function returns 0 in case of
|
|
|
|
|
* success, or a combination of ERR_* flags if an error is encountered. The
|
|
|
|
|
* function pointer can be NULL if not implemented. The function also has an
|
|
|
|
|
* access to the current "server" config line. The ->skip value tells the parser
|
|
|
|
|
* how many words have to be skipped after the keyword. If the function needs to
|
|
|
|
|
* parse more keywords, it needs to update cur_arg.
|
|
|
|
|
*/
|
|
|
|
|
struct srv_kw {
|
|
|
|
|
const char *kw;
|
|
|
|
|
int (*parse)(char **args, int *cur_arg, struct proxy *px, struct server *srv, char **err);
|
|
|
|
|
int skip; /* nb min of args to skip, for use when kw is not handled */
|
|
|
|
|
int default_ok; /* non-zero if kw is supported in default-server section */
|
2021-03-08 11:08:01 -05:00
|
|
|
int dynamic_ok; /* non-zero if kw is supported in add server cli command */
|
2012-10-10 02:27:36 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A keyword list. It is a NULL-terminated array of keywords. It embeds a
|
|
|
|
|
* struct list in order to be linked to other lists, allowing it to easily
|
|
|
|
|
* be declared where it is needed, and linked without duplicating data nor
|
|
|
|
|
* allocating memory. It is also possible to indicate a scope for the keywords.
|
|
|
|
|
*/
|
|
|
|
|
struct srv_kw_list {
|
|
|
|
|
const char *scope;
|
|
|
|
|
struct list list;
|
|
|
|
|
struct srv_kw kw[VAR_ARRAY];
|
|
|
|
|
};
|
2006-06-25 20:48:02 -04:00
|
|
|
|
2021-03-08 10:36:46 -05:00
|
|
|
#define SRV_PARSE_DEFAULT_SERVER 0x01 /* 'default-server' keyword */
|
|
|
|
|
#define SRV_PARSE_TEMPLATE 0x02 /* 'server-template' keyword */
|
|
|
|
|
#define SRV_PARSE_IN_PEER_SECTION 0x04 /* keyword in a peer section */
|
|
|
|
|
#define SRV_PARSE_PARSE_ADDR 0x08 /* required to parse the server address in the second argument */
|
2021-03-08 11:08:01 -05:00
|
|
|
#define SRV_PARSE_DYNAMIC 0x10 /* dynamic server created at runtime with cli */
|
|
|
|
|
#define SRV_PARSE_INITIAL_RESOLVE 0x20 /* resolve immediately the fqdn to an ip address */
|
2021-03-08 10:36:46 -05:00
|
|
|
|
2020-06-04 17:20:13 -04:00
|
|
|
#endif /* _HAPROXY_SERVER_T_H */
|
2006-06-25 20:48:02 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Local variables:
|
|
|
|
|
* c-indent-level: 8
|
|
|
|
|
* c-basic-offset: 8
|
|
|
|
|
* End:
|
|
|
|
|
*/
|