mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MINOR: listener: implement GUID support
This commit is similar with the two previous ones. Its purpose is to add GUID support on listeners. Due to bind_conf and listeners configuration, some specifities were required. Its possible to define several listeners on a single bind line, for example by specifying multiple addresses. As such, it's impossible to support a "guid" keyword on a bind line. The problem is exacerbated by the cloning of listeners when sharding is used. To resolve this, a new keyword "guid-prefix" is defined for bind lines. It allows to specify a string which will be used as a prefix for automatically generated GUID for each listeners attached to a bind_conf. Automatic GUID listeners generation is implemented via a new function bind_generate_guid(). It is called on post-parsing, after bind_complete_thread_setup(). For each listeners on a bind_conf, a new GUID is generated with bind_conf prefix and the index of the listener relative to other listeners in the bind_conf. This last value is stored in a new bind_conf field named <guid_idx>. If a GUID cannot be inserted, for example due to a non-unique value, an error is returned, startup is interrupted with configuration rejected.
This commit is contained in:
parent
8259456981
commit
0489d85263
@ -15908,6 +15908,12 @@ group <group>
|
|||||||
"gid" setting except that the group name is used instead of its gid. This
|
"gid" setting except that the group name is used instead of its gid. This
|
||||||
setting is ignored by non UNIX sockets.
|
setting is ignored by non UNIX sockets.
|
||||||
|
|
||||||
|
guid-prefix <string>
|
||||||
|
Generate case-sensitive global unique IDs for each listening sockets
|
||||||
|
allocated on this bind line. Prefix will be concatenated to listeners
|
||||||
|
position index on the current bind line, with character '-' as separator. See
|
||||||
|
"guid" proxy keyword description for more information on its format.
|
||||||
|
|
||||||
id <id>
|
id <id>
|
||||||
Fixes the socket ID. By default, socket IDs are automatically assigned, but
|
Fixes the socket ID. By default, socket IDs are automatically assigned, but
|
||||||
sometimes it is more convenient to fix them to ease monitoring. This value
|
sometimes it is more convenient to fix them to ease monitoring. This value
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <import/ebtree-t.h>
|
#include <import/ebtree-t.h>
|
||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
|
#include <haproxy/guid-t.h>
|
||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
#include <haproxy/quic_cc-t.h>
|
#include <haproxy/quic_cc-t.h>
|
||||||
#include <haproxy/quic_sock-t.h>
|
#include <haproxy/quic_sock-t.h>
|
||||||
@ -207,6 +208,8 @@ struct bind_conf {
|
|||||||
char *arg; /* argument passed to "bind" for better error reporting */
|
char *arg; /* argument passed to "bind" for better error reporting */
|
||||||
char *file; /* file where the section appears */
|
char *file; /* file where the section appears */
|
||||||
int line; /* line where the section appears */
|
int line; /* line where the section appears */
|
||||||
|
char *guid_prefix; /* prefix for listeners GUID */
|
||||||
|
size_t guid_idx; /* next index for listeners GUID generation */
|
||||||
char *rhttp_srvname; /* name of server when using "rhttp@" address */
|
char *rhttp_srvname; /* name of server when using "rhttp@" address */
|
||||||
int rhttp_nbconn; /* count of connections to initiate in parallel */
|
int rhttp_nbconn; /* count of connections to initiate in parallel */
|
||||||
__decl_thread(HA_RWLOCK_T sni_lock); /* lock the SNI trees during add/del operations */
|
__decl_thread(HA_RWLOCK_T sni_lock); /* lock the SNI trees during add/del operations */
|
||||||
@ -252,6 +255,8 @@ struct listener {
|
|||||||
struct eb32_node id; /* place in the tree of used IDs */
|
struct eb32_node id; /* place in the tree of used IDs */
|
||||||
} conf; /* config information */
|
} conf; /* config information */
|
||||||
|
|
||||||
|
struct guid_node guid; /* GUID global tree node */
|
||||||
|
|
||||||
struct li_per_thread *per_thr; /* per-thread fields (one per thread in the group) */
|
struct li_per_thread *per_thr; /* per-thread fields (one per thread in the group) */
|
||||||
|
|
||||||
EXTRA_COUNTERS(extra_counters);
|
EXTRA_COUNTERS(extra_counters);
|
||||||
|
@ -192,6 +192,13 @@ int default_resume_listener(struct listener *l);
|
|||||||
*/
|
*/
|
||||||
int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code);
|
int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code);
|
||||||
|
|
||||||
|
/* Generate and insert unique GUID for each listeners of <bind_conf> instance
|
||||||
|
* if GUID prefix is defined.
|
||||||
|
*
|
||||||
|
* Returns 0 on success else non-zero.
|
||||||
|
*/
|
||||||
|
int bind_generate_guid(struct bind_conf *bind_conf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
||||||
* parsing sessions.
|
* parsing sessions.
|
||||||
|
@ -2920,6 +2920,12 @@ int check_config_validity()
|
|||||||
if (err_code & ERR_FATAL)
|
if (err_code & ERR_FATAL)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bind_generate_guid(bind_conf)) {
|
||||||
|
cfgerr++;
|
||||||
|
err_code |= ERR_FATAL | ERR_ALERT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (curproxy->mode) {
|
switch (curproxy->mode) {
|
||||||
|
12
src/guid.c
12
src/guid.c
@ -1,6 +1,7 @@
|
|||||||
#include <haproxy/guid.h>
|
#include <haproxy/guid.h>
|
||||||
|
|
||||||
#include <import/ebistree.h>
|
#include <import/ebistree.h>
|
||||||
|
#include <haproxy/listener-t.h>
|
||||||
#include <haproxy/obj_type.h>
|
#include <haproxy/obj_type.h>
|
||||||
#include <haproxy/proxy.h>
|
#include <haproxy/proxy.h>
|
||||||
#include <haproxy/server-t.h>
|
#include <haproxy/server-t.h>
|
||||||
@ -46,6 +47,10 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
|
|||||||
guid = &__objt_proxy(objt)->guid;
|
guid = &__objt_proxy(objt)->guid;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OBJ_TYPE_LISTENER:
|
||||||
|
guid = &__objt_listener(objt)->guid;
|
||||||
|
break;
|
||||||
|
|
||||||
case OBJ_TYPE_SERVER:
|
case OBJ_TYPE_SERVER:
|
||||||
guid = &__objt_server(objt)->guid;
|
guid = &__objt_server(objt)->guid;
|
||||||
break;
|
break;
|
||||||
@ -115,6 +120,7 @@ char *guid_name(const struct guid_node *guid)
|
|||||||
{
|
{
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
struct proxy *px;
|
struct proxy *px;
|
||||||
|
struct listener *l;
|
||||||
struct server *srv;
|
struct server *srv;
|
||||||
|
|
||||||
switch (obj_type(guid->obj_type)) {
|
switch (obj_type(guid->obj_type)) {
|
||||||
@ -122,6 +128,12 @@ char *guid_name(const struct guid_node *guid)
|
|||||||
px = __objt_proxy(guid->obj_type);
|
px = __objt_proxy(guid->obj_type);
|
||||||
return memprintf(&msg, "%s %s", proxy_cap_str(px->cap), px->id);
|
return memprintf(&msg, "%s %s", proxy_cap_str(px->cap), px->id);
|
||||||
|
|
||||||
|
case OBJ_TYPE_LISTENER:
|
||||||
|
l = __objt_listener(guid->obj_type);
|
||||||
|
return memprintf(&msg, "listener %s (%s:%d)",
|
||||||
|
l->bind_conf->frontend->id,
|
||||||
|
l->bind_conf->file, l->bind_conf->line);
|
||||||
|
|
||||||
case OBJ_TYPE_SERVER:
|
case OBJ_TYPE_SERVER:
|
||||||
srv = __objt_server(guid->obj_type);
|
srv = __objt_server(guid->obj_type);
|
||||||
return memprintf(&msg, "server %s/%s", srv->proxy->id, srv->id);
|
return memprintf(&msg, "server %s/%s", srv->proxy->id, srv->id);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <haproxy/freq_ctr.h>
|
#include <haproxy/freq_ctr.h>
|
||||||
#include <haproxy/frontend.h>
|
#include <haproxy/frontend.h>
|
||||||
#include <haproxy/global.h>
|
#include <haproxy/global.h>
|
||||||
|
#include <haproxy/guid.h>
|
||||||
#include <haproxy/list.h>
|
#include <haproxy/list.h>
|
||||||
#include <haproxy/listener.h>
|
#include <haproxy/listener.h>
|
||||||
#include <haproxy/log.h>
|
#include <haproxy/log.h>
|
||||||
@ -816,6 +817,8 @@ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
|
|||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
l->rx.flags |= RX_F_INHERITED;
|
l->rx.flags |= RX_F_INHERITED;
|
||||||
|
|
||||||
|
guid_init(&l->guid);
|
||||||
|
|
||||||
l->extra_counters = NULL;
|
l->extra_counters = NULL;
|
||||||
|
|
||||||
HA_RWLOCK_INIT(&l->lock);
|
HA_RWLOCK_INIT(&l->lock);
|
||||||
@ -1832,6 +1835,43 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
|
|||||||
return cfgerr;
|
return cfgerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate and insert unique GUID for each listeners of <bind_conf> instance
|
||||||
|
* if GUID prefix is defined.
|
||||||
|
*
|
||||||
|
* Returns 0 on success else non-zero.
|
||||||
|
*/
|
||||||
|
int bind_generate_guid(struct bind_conf *bind_conf)
|
||||||
|
{
|
||||||
|
struct listener *l;
|
||||||
|
char *guid_err = NULL;
|
||||||
|
|
||||||
|
if (!bind_conf->guid_prefix)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list_for_each_entry(l, &bind_conf->listeners, by_bind) {
|
||||||
|
if (bind_conf->guid_idx == (size_t)-1) {
|
||||||
|
ha_alert("[%s:%d] : error on GUID generation : Too many listeners.\n",
|
||||||
|
bind_conf->file, bind_conf->line);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_printf(&trash, "%s-%lld", bind_conf->guid_prefix,
|
||||||
|
(ullong)bind_conf->guid_idx);
|
||||||
|
|
||||||
|
if (guid_insert(&l->obj_type, b_head(&trash), &guid_err)) {
|
||||||
|
ha_alert("[%s:%d] : error on GUID generation : %s. "
|
||||||
|
"You may fix it by adjusting guid-prefix.\n",
|
||||||
|
bind_conf->file, bind_conf->line, guid_err);
|
||||||
|
ha_free(&guid_err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++bind_conf->guid_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
* Registers the bind keyword list <kwl> as a list of valid keywords for next
|
||||||
* parsing sessions.
|
* parsing sessions.
|
||||||
@ -1975,6 +2015,9 @@ struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *file,
|
|||||||
#endif
|
#endif
|
||||||
LIST_INIT(&bind_conf->listeners);
|
LIST_INIT(&bind_conf->listeners);
|
||||||
|
|
||||||
|
bind_conf->guid_prefix = NULL;
|
||||||
|
bind_conf->guid_idx = 0;
|
||||||
|
|
||||||
bind_conf->rhttp_srvname = NULL;
|
bind_conf->rhttp_srvname = NULL;
|
||||||
|
|
||||||
return bind_conf;
|
return bind_conf;
|
||||||
@ -2082,6 +2125,26 @@ static int bind_parse_backlog(char **args, int cur_arg, struct proxy *px, struct
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse the "guid-prefix" bind keyword */
|
||||||
|
static int bind_parse_guid_prefix(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
||||||
|
{
|
||||||
|
char *prefix = NULL;
|
||||||
|
|
||||||
|
if (!*args[cur_arg + 1]) {
|
||||||
|
memprintf(err, "'%s' : expects an argument", args[cur_arg]);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = strdup(args[cur_arg + 1]);
|
||||||
|
if (!prefix) {
|
||||||
|
memprintf(err, "'%s' : out of memory", args[cur_arg]);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->guid_prefix = prefix;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse the "id" bind keyword */
|
/* parse the "id" bind keyword */
|
||||||
static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
static int bind_parse_id(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
||||||
{
|
{
|
||||||
@ -2486,6 +2549,7 @@ static struct bind_kw_list bind_kws = { "ALL", { }, {
|
|||||||
{ "accept-netscaler-cip", bind_parse_accept_netscaler_cip, 1, 0 }, /* enable NetScaler Client IP insertion protocol */
|
{ "accept-netscaler-cip", bind_parse_accept_netscaler_cip, 1, 0 }, /* enable NetScaler Client IP insertion protocol */
|
||||||
{ "accept-proxy", bind_parse_accept_proxy, 0, 0 }, /* enable PROXY protocol */
|
{ "accept-proxy", bind_parse_accept_proxy, 0, 0 }, /* enable PROXY protocol */
|
||||||
{ "backlog", bind_parse_backlog, 1, 0 }, /* set backlog of listening socket */
|
{ "backlog", bind_parse_backlog, 1, 0 }, /* set backlog of listening socket */
|
||||||
|
{ "guid-prefix", bind_parse_guid_prefix, 1, 1 }, /* set guid of listening socket */
|
||||||
{ "id", bind_parse_id, 1, 1 }, /* set id of listening socket */
|
{ "id", bind_parse_id, 1, 1 }, /* set id of listening socket */
|
||||||
{ "maxconn", bind_parse_maxconn, 1, 0 }, /* set maxconn of listening socket */
|
{ "maxconn", bind_parse_maxconn, 1, 0 }, /* set maxconn of listening socket */
|
||||||
{ "name", bind_parse_name, 1, 1 }, /* set name of listening socket */
|
{ "name", bind_parse_name, 1, 1 }, /* set name of listening socket */
|
||||||
|
@ -316,6 +316,7 @@ void free_proxy(struct proxy *p)
|
|||||||
srv_free_params(&p->defsrv);
|
srv_free_params(&p->defsrv);
|
||||||
|
|
||||||
list_for_each_entry_safe(l, l_next, &p->conf.listeners, by_fe) {
|
list_for_each_entry_safe(l, l_next, &p->conf.listeners, by_fe) {
|
||||||
|
guid_remove(&l->guid);
|
||||||
LIST_DELETE(&l->by_fe);
|
LIST_DELETE(&l->by_fe);
|
||||||
LIST_DELETE(&l->by_bind);
|
LIST_DELETE(&l->by_bind);
|
||||||
free(l->name);
|
free(l->name);
|
||||||
@ -335,6 +336,7 @@ void free_proxy(struct proxy *p)
|
|||||||
free(bind_conf->arg);
|
free(bind_conf->arg);
|
||||||
free(bind_conf->settings.interface);
|
free(bind_conf->settings.interface);
|
||||||
LIST_DELETE(&bind_conf->by_fe);
|
LIST_DELETE(&bind_conf->by_fe);
|
||||||
|
free(bind_conf->guid_prefix);
|
||||||
free(bind_conf->rhttp_srvname);
|
free(bind_conf->rhttp_srvname);
|
||||||
free(bind_conf);
|
free(bind_conf);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user