From 129ecf441f9be70ff3e39fd3b84964e0c4bf2718 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Thu, 17 Nov 2022 10:37:58 +0100 Subject: [PATCH] MINOR: server/event_hdl: add support for SERVER_ADD and SERVER_DEL events Basic support for ADD and DEL server events are added through this commit: SERVER_ADD is published on dynamic server addition through cli. SERVER_DEL is published on dynamic server deletion through cli. This work depends on: "MINOR: event_hdl: add event handler base api" "MINOR: server: add srv->rid (revision id) value" --- include/haproxy/server-t.h | 32 ++++++++++++++++++++++++++++++ src/server.c | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index dd42807d8c..dd1a3afa0d 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -40,6 +40,7 @@ #include #include #include +#include /* server states. Only SRV_ST_STOPPED indicates a down server. */ @@ -403,6 +404,8 @@ struct server { } op_st_chg; /* operational status change's reason */ char adm_st_chg_cause[48]; /* administrative status change's cause */ + event_hdl_sub_list e_subs; /* event_hdl: server's subscribers list (atomically updated) */ + /* 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 */ @@ -411,6 +414,35 @@ struct server { EXTRA_COUNTERS(extra_counters); }; +/* 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 + * EVENT_HDL_SUB_SERVER_DOWN + */ + 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 */ + int puid; /* proxy-unique server ID */ + int rid; /* server id revision */ + 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 */ + } unsafe; +}; /* Storage structure to load server-state lines from a flat file into * an ebtree, for faster processing diff --git a/src/server.c b/src/server.c index bc8d0cba54..eddaf9107b 100644 --- a/src/server.c +++ b/src/server.c @@ -47,6 +47,7 @@ #include #include #include +#include static void srv_update_status(struct server *s); @@ -132,6 +133,33 @@ int srv_getinter(const struct check *check) return (check->fastinter)?(check->fastinter):(check->inter); } +/* + * Use this to publish EVENT_HDL_SUB_SERVER family type event + * from srv facility + * Event will be published in both global subscription list and + * server dedicated subscription list + * server ptr must be valid + */ +static inline void srv_event_hdl_publish(struct event_hdl_sub_type event, struct server *srv, uint8_t thread_isolate) +{ + struct event_hdl_cb_data_server cb_data; + + /* safe data assignments */ + cb_data.safe.puid = srv->puid; + cb_data.safe.rid = srv->rid; + cb_data.safe.flags = srv->flags; + snprintf(cb_data.safe.name, sizeof(cb_data.safe.name), "%s", srv->id); + if (srv->proxy) + snprintf(cb_data.safe.proxy_name, sizeof(cb_data.safe.proxy_name), "%s", srv->proxy->id); + /* unsafe data assignments */ + cb_data.unsafe.ptr = srv; + cb_data.unsafe.thread_isolate = thread_isolate; + /* publish in server dedicated sub list */ + event_hdl_publish(&srv->e_subs, event, EVENT_HDL_CB_DATA(&cb_data)); + /* publish in global subscription list */ + event_hdl_publish(NULL, event, EVENT_HDL_CB_DATA(&cb_data)); +} + /* * Check that we did not get a hash collision. * Unlikely, but it can happen. The server's proxy must be at least @@ -2337,6 +2365,7 @@ struct server *new_server(struct proxy *proxy) LIST_APPEND(&servers_list, &srv->global_list); LIST_INIT(&srv->srv_rec_item); LIST_INIT(&srv->ip_rec_item); + event_hdl_sub_list_init(&srv->e_subs); srv->next_state = SRV_ST_RUNNING; /* early server setup */ srv->last_change = now.tv_sec; @@ -2419,6 +2448,7 @@ struct server *srv_drop(struct server *srv) HA_SPIN_DESTROY(&srv->lock); LIST_DELETE(&srv->global_list); + event_hdl_sub_list_destroy(&srv->e_subs); EXTRA_COUNTERS_FREE(srv->extra_counters); @@ -4893,6 +4923,11 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct */ srv->rid = (srv_id_reuse_cnt) ? (srv_id_reuse_cnt / 2) : 0; + /* adding server cannot fail when we reach this: + * publishing EVENT_HDL_SUB_SERVER_ADD + */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_ADD, srv, 1); + thread_release(); /* Start the check task. The server must be fully initialized. @@ -5020,6 +5055,11 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap goto out; } + /* removing cannot fail anymore when we reach this: + * publishing EVENT_HDL_SUB_SERVER_DEL + */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DEL, srv, 1); + /* remove srv from tracking list */ if (srv->track) release_server_track(srv); -- 2.39.5