Store HTTP quota size inside a listenlist instead of the quota

This way only quota size is passed to the interface/listener
management code instead of a quota object. Thus, we can implement
updating the quota object size instead of recreating the object.
This commit is contained in:
Artem Boldariev 2022-06-22 14:52:58 +03:00
parent 806b89abe1
commit 3f0b310772
7 changed files with 56 additions and 30 deletions

View file

@ -11226,8 +11226,6 @@ listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
size_t len = 1, i = 0;
uint32_t max_clients = named_g_http_listener_clients;
uint32_t max_streams = named_g_http_streams_per_conn;
ns_server_t *server = NULL;
isc_quota_t *quota = NULL;
REQUIRE(target != NULL && *target == NULL);
@ -11282,24 +11280,13 @@ listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
INSIST(i == len);
INSIST(named_g_server != NULL);
ns_server_attach(named_g_server->sctx, &server);
if (max_clients > 0) {
quota = isc_mem_get(mctx, sizeof(isc_quota_t));
isc_quota_init(quota, max_clients);
}
result = ns_listenelt_create_http(
mctx, port, named_g_dscp, NULL, family, tls, tls_params,
tlsctx_cache, endpoints, len, quota, max_streams, &delt);
tlsctx_cache, endpoints, len, max_clients, max_streams, &delt);
if (result != ISC_R_SUCCESS) {
goto error;
}
if (quota != NULL) {
ISC_LIST_APPEND(server->http_quotas, quota, link);
}
ns_server_detach(&server);
*target = delt;
return (result);
@ -11307,14 +11294,6 @@ error:
if (delt != NULL) {
ns_listenelt_destroy(delt);
}
if (quota != NULL) {
isc_quota_destroy(quota);
isc_mem_put(mctx, quota, sizeof(*quota));
}
if (server != NULL) {
ns_server_detach(&server);
}
return (result);
}
#endif /* HAVE_LIBNGHTTP2 */

View file

@ -79,6 +79,7 @@ struct ns_interface {
isc_nmsocket_t *tcplistensocket;
isc_nmsocket_t *http_listensocket;
isc_nmsocket_t *http_secure_listensocket;
isc_quota_t *http_quota;
isc_dscp_t dscp; /*%< "listen-on" DSCP value */
isc_refcount_t ntcpaccepting; /*%< Number of clients
* ready to accept new

View file

@ -50,7 +50,7 @@ struct ns_listenelt {
isc_tlsctx_cache_t *sslctx_cache;
char **http_endpoints;
size_t http_endpoints_number;
isc_quota_t *http_quota;
uint32_t http_max_clients;
uint32_t max_concurrent_streams;
ISC_LINK(ns_listenelt_t) link;
};
@ -98,7 +98,7 @@ ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
size_t nendpoints, isc_quota_t *quota,
size_t nendpoints, const uint32_t max_clients,
const uint32_t max_streams, ns_listenelt_t **target);
/*%<
* Create a listen-on list element for HTTP(S).

View file

@ -85,6 +85,7 @@ struct ns_server {
isc_quota_t tcpquota;
isc_quota_t xfroutquota;
ISC_LIST(isc_quota_t) http_quotas;
isc_mutex_t http_quotas_lock;
/*% Test options and other configurables */
uint32_t options;
@ -183,3 +184,13 @@ ns_server_getoption(ns_server_t *sctx, unsigned int option);
* Requires:
*\li 'sctx' is valid.
*/
void
ns_server_append_http_quota(ns_server_t *sctx, isc_quota_t *http_quota);
/*%<
* Add a quota to the list of HTTP quotas to destroy it safely later.
*
* Requires:
*\li 'sctx' is valid;
*\li 'http_quota' is not 'NULL'.
*/

View file

@ -572,12 +572,13 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
static isc_result_t
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
size_t neps, isc_quota_t *quota,
size_t neps, uint32_t max_clients,
uint32_t max_concurrent_streams) {
#if HAVE_LIBNGHTTP2
isc_result_t result = ISC_R_FAILURE;
isc_nmsocket_t *sock = NULL;
isc_nm_http_endpoints_t *epset = NULL;
isc_quota_t *quota = NULL;
epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
@ -590,6 +591,8 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
}
if (result == ISC_R_SUCCESS) {
quota = isc_mem_get(ifp->mgr->mctx, sizeof(*quota));
isc_quota_init(quota, max_clients);
result = isc_nm_listenhttp(ifp->mgr->nm, ISC_NM_LISTEN_ALL,
&ifp->addr, ifp->mgr->backlog, quota,
sslctx, epset,
@ -598,6 +601,16 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
isc_nm_http_endpoints_detach(&epset);
if (quota != NULL) {
if (result != ISC_R_SUCCESS) {
isc_quota_destroy(quota);
isc_mem_put(ifp->mgr->mctx, quota, sizeof(*quota));
} else {
ifp->http_quota = quota;
ns_server_append_http_quota(ifp->mgr->sctx, quota);
}
}
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"creating %s socket: %s",
@ -630,7 +643,7 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
UNUSED(sslctx);
UNUSED(eps);
UNUSED(neps);
UNUSED(quota);
UNUSED(max_clients);
UNUSED(max_concurrent_streams);
return (ISC_R_NOTIMPLEMENTED);
#endif
@ -660,7 +673,7 @@ interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name,
if (elt->is_http) {
result = ns_interface_listenhttp(
ifp, elt->sslctx, elt->http_endpoints,
elt->http_endpoints_number, elt->http_quota,
elt->http_endpoints_number, elt->http_max_clients,
elt->max_concurrent_streams);
if (result != ISC_R_SUCCESS) {
goto cleanup_interface;
@ -731,6 +744,7 @@ ns_interface_shutdown(ns_interface_t *ifp) {
isc_nm_stoplistening(ifp->http_secure_listensocket);
isc_nmsocket_close(&ifp->http_secure_listensocket);
}
ifp->http_quota = NULL;
}
static void

View file

@ -171,7 +171,8 @@ listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
}
elt->http_endpoints = NULL;
elt->http_endpoints_number = 0;
elt->http_quota = NULL;
elt->http_max_clients = 0;
elt->max_concurrent_streams = 0;
*target = elt;
return (ISC_R_SUCCESS);
@ -200,7 +201,7 @@ ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
size_t nendpoints, isc_quota_t *quota,
size_t nendpoints, const uint32_t max_clients,
const uint32_t max_streams, ns_listenelt_t **target) {
isc_result_t result;
@ -214,7 +215,14 @@ ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
(*target)->is_http = true;
(*target)->http_endpoints = endpoints;
(*target)->http_endpoints_number = nendpoints;
(*target)->http_quota = quota;
/*
* 0 sized quota - means unlimited quota. We used to not
* create a quota object in such a case, but we might need to
* update the value of the quota during reconfiguration, so we
* need to have a quota object in place anyway.
*/
(*target)->http_max_clients = max_clients == 0 ? UINT32_MAX
: max_clients;
(*target)->max_concurrent_streams = max_streams;
} else {
size_t i;

View file

@ -55,6 +55,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
isc_quota_init(&sctx->tcpquota, 10);
isc_quota_init(&sctx->recursionquota, 100);
ISC_LIST_INIT(sctx->http_quotas);
isc_mutex_init(&sctx->http_quotas_lock);
CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx));
@ -150,6 +151,7 @@ ns_server_detach(ns_server_t **sctxp) {
sizeof(*http_quota));
http_quota = next;
}
isc_mutex_destroy(&sctx->http_quotas_lock);
if (sctx->server_id != NULL) {
isc_mem_free(sctx->mctx, sctx->server_id);
@ -240,3 +242,14 @@ ns_server_getoption(ns_server_t *sctx, unsigned int option) {
return ((sctx->options & option) != 0);
}
void
ns_server_append_http_quota(ns_server_t *sctx, isc_quota_t *http_quota) {
REQUIRE(SCTX_VALID(sctx));
REQUIRE(http_quota != NULL);
LOCK(&sctx->http_quotas_lock);
ISC_LINK_INIT(http_quota, link);
ISC_LIST_APPEND(sctx->http_quotas, http_quota, link);
UNLOCK(&sctx->http_quotas_lock);
}