haproxy/include/haproxy/counters-t.h
Aurelien DARRAGON d30b88a6cc BUG/MAJOR: stats-file: ensure shm_stats_file_object struct mapping consistency
As reported by @tianon on GH #3168, running haproxy on 32bits i386
platform would trigger the following BUG_ON() statement:

 FATAL: bug condition "sizeof(struct shm_stats_file_object) != 544" matched at src/stats-file.c:825
shm_stats_file_object struct size changed, is is part of the exported API: ensure all precautions were taken (ie: shm_stats_file version change) before adjusting this

In fact, some efforts were already taken to ensure shm_stats_file_object
struct size remains consistent on 64 vs 32 bits platforms, since
shm_stats_file_object is part of the public API and directly exposed in
the stats file.

However, some parts were overlooked: some structs that are embedded in
shm_stats_file_object struct itself weren't using fixed-width integers,
and would sometime be unaligned. The result of this is that it was
up to the compiler (platform-dependent) to choose how to deal with such
ambiguities, which could cause the struct mapping/size to be inconsistent
from one platform to another.

Hopefully this was caught by the BUG_ON() statement and with the precious
help of @tianon

To fix this, we now use fixed-width integers everywhere for members
(and submembers) of shm_stats_file_object struct, and we use explicit
padding where missing to avoid automatic padding when we don't expect
one. As for the previous commit, we leverage FIXED_SIZE() and
FIXED_SIZE_ARRAY() macro to set the expected width for each integer
without causing build issues on platform that don't support larger
integers.

No backport needed, this feature was introduced during 3.3-dev.
2025-10-22 20:52:22 +02:00

194 lines
9.4 KiB
C

/*
* include/haproxy/counters-t.h
* This file contains structure declarations for statistics counters.
*
* Copyright 2008-2009 Krzysztof Piotr Oledzki <ole@ans.pl>
* Copyright 2011-2014 Willy Tarreau <w@1wt.eu>
*
* 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_COUNTERS_T_H
#define _HAPROXY_COUNTERS_T_H
#include <haproxy/freq_ctr-t.h>
#define COUNTERS_SHARED_F_NONE 0x0000
#define COUNTERS_SHARED_F_LOCAL 0x0001 // shared counter struct is actually process-local
// common to fe_counters_shared and be_counters_shared
#define COUNTERS_SHARED \
struct { \
uint16_t flags; /* COUNTERS_SHARED_F flags */\
};
/* /!\ any change performed here will impact shm-stats-file mapping because the
* struct is embedded in shm_stats_file_object struct, so proceed with caution
* and change shm stats file version if needed
*/
#define COUNTERS_SHARED_TG \
struct { \
FIXED_SIZE(8, unsigned long, last_state_change); /* last time, when the state was changed */\
FIXED_SIZE(8, long long, srv_aborts); /* aborted responses during DATA phase caused by the server */\
FIXED_SIZE(8, long long, cli_aborts); /* aborted responses during DATA phase caused by the client */\
FIXED_SIZE(8, long long, internal_errors); /* internal processing errors */\
FIXED_SIZE(8, long long, failed_rewrites); /* failed rewrites (warning) */\
FIXED_SIZE(8, long long, bytes_out); /* number of bytes transferred from the server to the client */\
FIXED_SIZE(8, long long, bytes_in); /* number of bytes transferred from the client to the server */\
FIXED_SIZE(8, long long, denied_resp); /* blocked responses because of security concerns */\
FIXED_SIZE(8, long long, denied_req); /* blocked requests because of security concerns */\
FIXED_SIZE(8, long long, cum_sess); /* cumulated number of accepted connections */\
/* compression counters, index 0 for requests, 1 for responses */\
FIXED_SIZE_ARRAY(8, 2, long long, comp_in); /* input bytes fed to the compressor */\
FIXED_SIZE_ARRAY(8, 2, long long, comp_out); /* output bytes emitted by the compressor */\
FIXED_SIZE_ARRAY(8, 2, long long, comp_byp); /* input bytes that bypassed the compressor (cpu/ram/bw limitation) */\
struct freq_ctr sess_per_sec; /* sessions per second on this server */\
ALWAYS_PAD(4); /* ensure 4 bytes hole is consistent 32bits vs 64 bits systems */\
};
// for convenience (generic pointer)
struct counters_shared {
COUNTERS_SHARED;
struct {
COUNTERS_SHARED_TG;
} *tg[MAX_TGROUPS];
};
/*
* /!\ any change performed here will impact shm-stats-file mapping because the
* struct is embedded in shm_stats_file_object struct, so proceed with caution
* and change shm stats file version if needed
*
* fixed width integers should be used
*/
struct fe_counters_shared_tg {
COUNTERS_SHARED_TG;
FIXED_SIZE(8, long long, denied_sess); /* denied session requests (tcp-req-sess rules) */
FIXED_SIZE(8, long long, denied_conn); /* denied connection requests (tcp-req-conn rules) */
FIXED_SIZE(8, long long, intercepted_req); /* number of monitoring or stats requests intercepted by the frontend */
FIXED_SIZE(8, long long, cum_conn); /* cumulated number of received connections */
struct freq_ctr conn_per_sec; /* received connections per second on the frontend */
struct freq_ctr req_per_sec; /* HTTP requests per second on the frontend */
FIXED_SIZE_ARRAY(8, 3, long long, cum_sess_ver); /* cumulated number of h1/h2/h3 sessions */
union {
struct {
FIXED_SIZE_ARRAY(8, 4, long long, cum_req); /* cumulated number of processed other/h1/h2/h3 requests */
FIXED_SIZE(8, long long, cache_hits); /* cache hits */
FIXED_SIZE(8, long long, cache_lookups); /* cache lookups */
FIXED_SIZE(8, long long, comp_rsp); /* number of compressed responses */
FIXED_SIZE_ARRAY(8, 6, long long, rsp); /* http response codes */
} http;
} p; /* protocol-specific stats */
FIXED_SIZE(8, long long, failed_req); /* failed requests (eg: invalid or timeout) */
};
struct fe_counters_shared {
COUNTERS_SHARED;
struct fe_counters_shared_tg *tg[MAX_TGROUPS];
};
/* counters used by listeners and frontends */
struct fe_counters {
struct fe_counters_shared shared; /* shared counters */
unsigned int conn_max; /* max # of active sessions */
unsigned int cps_max; /* maximum of new connections received per second */
unsigned int sps_max; /* maximum of new connections accepted per second (sessions) */
struct freq_ctr _sess_per_sec; /* sessions per second on this frontend, used to compute sps_max (internal use only) */
struct freq_ctr _conn_per_sec; /* connections per second on this frontend, used to compute cps_max (internal use only) */
union {
struct {
unsigned int rps_max; /* maximum of new HTTP requests second observed */
struct freq_ctr _req_per_sec; /* HTTP requests per second on the frontend, only used to compute rps_max */
} http;
} p; /* protocol-specific stats */
};
/* /!\ any change performed here will impact shm-stats-file mapping because the
* struct is embedded in shm_stats_file_object struct, so proceed with caution
* and change shm stats file version if needed
*
* fixed width integer types should be used
*/
struct be_counters_shared_tg {
COUNTERS_SHARED_TG;
FIXED_SIZE(8, long long, cum_lbconn); /* cumulated number of sessions processed by load balancing (BE only) */
FIXED_SIZE(8, long long, connect); /* number of connection establishment attempts */
FIXED_SIZE(8, long long, reuse); /* number of connection reuses */
FIXED_SIZE(8, unsigned long, last_sess); /* last session time */
FIXED_SIZE(8, long long, failed_checks); /* failed health checks */
FIXED_SIZE(8, long long, failed_hana); /* failed health analyses */
FIXED_SIZE(8, long long, down_trans); /* up->down transitions */
union {
struct {
FIXED_SIZE(8, long long, cum_req); /* cumulated number of processed HTTP requests */
FIXED_SIZE(8, long long, cache_hits); /* cache hits */
FIXED_SIZE(8, long long, cache_lookups);/* cache lookups */
FIXED_SIZE(8, long long, comp_rsp); /* number of compressed responses */
FIXED_SIZE_ARRAY(8, 6, long long, rsp); /* http response codes */
} http;
} p; /* protocol-specific stats */
FIXED_SIZE(8, long long, redispatches); /* retried and redispatched connections (BE only) */
FIXED_SIZE(8, long long, retries); /* retried and redispatched connections (BE only) */
FIXED_SIZE(8, long long, failed_resp); /* failed responses (BE only) */
FIXED_SIZE(8, long long, failed_conns); /* failed connect() attempts (BE only) */
};
struct be_counters_shared {
COUNTERS_SHARED;
struct be_counters_shared_tg *tg[MAX_TGROUPS];
};
/* counters used by servers and backends */
struct be_counters {
struct be_counters_shared shared; /* shared counters */
unsigned int conn_max; /* max # of active sessions */
unsigned int cps_max; /* maximum of new connections received per second */
unsigned int sps_max; /* maximum of new connections accepted per second (sessions) */
unsigned int nbpend_max; /* max number of pending connections with no server assigned yet */
unsigned int cur_sess_max; /* max number of currently active sessions */
struct freq_ctr _sess_per_sec; /* sessions per second on this frontend, used to compute sps_max (internal use only) */
unsigned int q_time, c_time, d_time, t_time; /* sums of conn_time, queue_time, data_time, total_time */
unsigned int qtime_max, ctime_max, dtime_max, ttime_max; /* maximum of conn_time, queue_time, data_time, total_time observed */
union {
struct {
unsigned int rps_max; /* maximum of new HTTP requests second observed */
} http;
} p; /* protocol-specific stats */
};
#endif /* _HAPROXY_COUNTERS_T_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/