]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Store HTTP quota size inside a listenlist instead of the quota
authorArtem Boldariev <artem@boldariev.com>
Wed, 22 Jun 2022 11:52:58 +0000 (14:52 +0300)
committerArtem Boldariev <artem@boldariev.com>
Tue, 28 Jun 2022 12:42:38 +0000 (15:42 +0300)
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.

bin/named/server.c
lib/ns/include/ns/interfacemgr.h
lib/ns/include/ns/listenlist.h
lib/ns/include/ns/server.h
lib/ns/interfacemgr.c
lib/ns/listenlist.c
lib/ns/server.c

index e36502863a3a19c2d34d5ac61f5e4ea2a7e35577..a8ba34457a2e228cf8ec649f83e24b7e95b3c017 100644 (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 */
index 87d7df98189cad482e3858590c7466cf98b93763..ac94c7957af159da5ae9778af742aa71fc790722 100644 (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
index cf433b5028ce1f2b2f95bb231487c2e71862ca11..cbb099c23819535b8f8910f67106b768b0837861 100644 (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).
index 1a2135824d391f249313c8b05f07126e49be1e82..51c2c0a1d540118310936ada000b8f85cab3a79e 100644 (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'.
+ */
index 118b7c03678d7ea0c73912be57077a5e88e6ac32..a70027a4cd6384706cfc7d63b5b429fc106033fb 100644 (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
index f852f06d567e141aad12c480357376f93dae9945..85fc12eb631a6c2a26ad0617843d984d10bf60cb 100644 (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;
index 57bb753179d4f13a8a2d19b544b983bab6ccb4fe..4a738118b1277efa38a57ab52d113e62b41ca177 100644 (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);
+}