MINOR: proto_reverse_connect: emit log for preconnect

Add reporting using send_log() for preconnect operation. This is minimal
to ensure we understand the current status of listener in active reverse
connect.

To limit logging quantity, only important transition are considered.
This requires to implement a minimal state machine as a new field in
receiver structure.

Here are the logs produced :
* Initiating : first time preconnect is enabled on a listener
* Error : last preconnect attempt interrupted on a connection error
* Reaching maxconn : all necessary connections were reversed and are
  operational on a listener
This commit is contained in:
Amaury Denoyelle 2023-09-22 15:55:24 +02:00
parent 069ca55e70
commit b9bb3b932c
4 changed files with 40 additions and 1 deletions

View File

@ -0,0 +1,14 @@
#ifndef _HAPROXY_PROTO_REVERSE_CONNECT_H_T
#define _HAPROXY_PROTO_REVERSE_CONNECT_H_T
/* State for reverse preconnect listener state machine.
* Used to limit log reporting only on state changes.
*/
enum li_preconn_state {
LI_PRECONN_ST_STOP, /* pre-connect task inactive */
LI_PRECONN_ST_INIT, /* pre-connect task bootstrapped */
LI_PRECONN_ST_ERR, /* last pre-connect attempt failed */
LI_PRECONN_ST_FULL, /* pre-connect maxconn reached */
};
#endif /* _HAPROXY_PROTO_REVERSE_CONNECT_H_T */

View File

@ -27,6 +27,7 @@
#include <haproxy/api-t.h>
#include <haproxy/namespace-t.h>
#include <haproxy/proto_reverse_connect-t.h>
#include <haproxy/thread.h>
/* Bit values for receiver->flags */
@ -83,6 +84,7 @@ struct receiver {
struct task *task; /* Task used to open connection for reverse. */
struct server *srv; /* Underlying server used to initiate reverse pre-connect. */
struct connection *pend_conn; /* Pending connection waiting to complete reversal before being accepted. */
enum li_preconn_state state; /* State for transition logging. */
} reverse_connect;
/* warning: this struct is huge, keep it at the bottom */

View File

@ -22,7 +22,7 @@
#include <haproxy/frontend.h>
#include <haproxy/hash.h>
#include <haproxy/list.h>
#include <haproxy/log-t.h>
#include <haproxy/log.h>
#include <haproxy/namespace.h>
#include <haproxy/net_helper.h>
#include <haproxy/proto_reverse_connect.h>

View File

@ -6,6 +6,7 @@
#include <haproxy/errors.h>
#include <haproxy/list.h>
#include <haproxy/listener.h>
#include <haproxy/log.h>
#include <haproxy/proto_tcp.h>
#include <haproxy/protocol.h>
#include <haproxy/proxy.h>
@ -117,6 +118,13 @@ void rev_notify_preconn_err(struct listener *l)
/* Remove reference to the freed connection. */
l->rx.reverse_connect.pend_conn = NULL;
if (l->rx.reverse_connect.state != LI_PRECONN_ST_ERR) {
send_log(l->bind_conf->frontend, LOG_ERR,
"preconnect %s::%s: Error encountered.\n",
l->bind_conf->frontend->id, l->bind_conf->reverse_srvname);
l->rx.reverse_connect.state = LI_PRECONN_ST_ERR;
}
/* Rearm a new preconnect attempt. */
l->rx.reverse_connect.task->expire = MS_TO_TICKS(now_ms + 1000);
task_queue(l->rx.reverse_connect.task);
@ -182,6 +190,7 @@ int rev_bind_listener(struct listener *listener, char *errmsg, int errlen)
task->process = rev_process;
task->context = listener;
listener->rx.reverse_connect.task = task;
listener->rx.reverse_connect.state = LI_PRECONN_ST_STOP;
/* Set a default maxconn to 1. This ensures listener is properly
* reenable each time we fall back below it on connection error.
@ -241,11 +250,25 @@ int rev_bind_listener(struct listener *listener, char *errmsg, int errlen)
void rev_enable_listener(struct listener *l)
{
if (l->rx.reverse_connect.state < LI_PRECONN_ST_INIT) {
send_log(l->bind_conf->frontend, LOG_INFO,
"preconnect %s::%s: Initiating.\n",
l->bind_conf->frontend->id, l->bind_conf->reverse_srvname);
l->rx.reverse_connect.state = LI_PRECONN_ST_INIT;
}
task_wakeup(l->rx.reverse_connect.task, TASK_WOKEN_ANY);
}
void rev_disable_listener(struct listener *l)
{
if (l->rx.reverse_connect.state < LI_PRECONN_ST_FULL) {
send_log(l->bind_conf->frontend, LOG_INFO,
"preconnect %s::%s: Reaching maxconn %d.\n",
l->bind_conf->frontend->id, l->bind_conf->reverse_srvname,
l->bind_conf->maxconn);
l->rx.reverse_connect.state = LI_PRECONN_ST_FULL;
}
}
struct connection *rev_accept_conn(struct listener *l, int *status)