https://bugzilla.redhat.com/show_bug.cgi?id=981729
This config tunable allows users to determine the maximum number of
accepted but yet not authenticated users.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
daemon/libvirtd-config.c | 1 +
daemon/libvirtd-config.h | 1 +
daemon/libvirtd.aug | 1 +
daemon/libvirtd.c | 1 +
daemon/libvirtd.conf | 4 ++++
daemon/test_libvirtd.aug.in | 1 +
src/locking/lock_daemon.c | 3 +--
src/lxc/lxc_controller.c | 2 +-
src/rpc/virnetserver.c | 52 +++++++++++++++++++++++++++++++++++++++++++--
src/rpc/virnetserver.h | 1 +
10 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/daemon/libvirtd-config.c b/daemon/libvirtd-config.c
index c816fda..04482c5 100644
--- a/daemon/libvirtd-config.c
+++ b/daemon/libvirtd-config.c
@@ -415,6 +415,7 @@ daemonConfigLoadOptions(struct daemonConfig *data,
GET_CONF_INT(conf, filename, max_workers);
GET_CONF_INT(conf, filename, max_clients);
GET_CONF_INT(conf, filename, max_queued_clients);
+ GET_CONF_INT(conf, filename, max_anonymous_clients);
GET_CONF_INT(conf, filename, prio_workers);
diff --git a/daemon/libvirtd-config.h b/daemon/libvirtd-config.h
index a24d5d2..66dc80b 100644
--- a/daemon/libvirtd-config.h
+++ b/daemon/libvirtd-config.h
@@ -64,6 +64,7 @@ struct daemonConfig {
int max_workers;
int max_clients;
int max_queued_clients;
+ int max_anonymous_clients;
int prio_workers;
diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug
index 70fce5c..5a0807c 100644
--- a/daemon/libvirtd.aug
+++ b/daemon/libvirtd.aug
@@ -57,6 +57,7 @@ module Libvirtd =
| int_entry "max_workers"
| int_entry "max_clients"
| int_entry "max_queued_clients"
+ | int_entry "max_anonymous_clients"
| int_entry "max_requests"
| int_entry "max_client_requests"
| int_entry "prio_workers"
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index b27c6fd..6e4c06f 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1376,6 +1376,7 @@ int main(int argc, char **argv) {
config->max_workers,
config->prio_workers,
config->max_clients,
+ config->max_anonymous_clients,
config->keepalive_interval,
config->keepalive_count,
!!config->keepalive_required,
diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf
index 073c178..880f46a 100644
--- a/daemon/libvirtd.conf
+++ b/daemon/libvirtd.conf
@@ -263,6 +263,10 @@
# connection succeeds.
#max_queued_clients = 1000
+# The maximum length of queue of accepted but not yet not
+# authenticated clients. The default value is zero, meaning
+# the feature is disabled.
+#max_anonymous_clients = 20
# The minimum limit sets the number of workers to start up
# initially. If the number of active clients exceeds this,
diff --git a/daemon/test_libvirtd.aug.in b/daemon/test_libvirtd.aug.in
index a7e8515..b03451c 100644
--- a/daemon/test_libvirtd.aug.in
+++ b/daemon/test_libvirtd.aug.in
@@ -36,6 +36,7 @@ module Test_libvirtd =
}
{ "max_clients" = "20" }
{ "max_queued_clients" = "1000" }
+ { "max_anonymous_clients" = "20" }
{ "min_workers" = "5" }
{ "max_workers" = "20" }
{ "prio_workers" = "5" }
diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c
index e047751..054ece2 100644
--- a/src/locking/lock_daemon.c
+++ b/src/locking/lock_daemon.c
@@ -145,8 +145,7 @@ virLockDaemonNew(virLockDaemonConfigPtr config, bool privileged)
}
if (!(lockd->srv = virNetServerNew(1, 1, 0, config->max_clients,
- -1, 0,
- false, NULL,
+ 0, -1, 0, false, NULL,
virLockDaemonClientNew,
virLockDaemonClientPreExecRestart,
virLockDaemonClientFree,
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 5ca960f..dcb8264 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -736,7 +736,7 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl)
LXC_STATE_DIR, ctrl->name) < 0)
return -1;
- if (!(ctrl->server = virNetServerNew(0, 0, 0, 1,
+ if (!(ctrl->server = virNetServerNew(0, 0, 0, 1, 1,
-1, 0, false,
NULL,
virLXCControllerClientPrivateNew,
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 6b3f5f0..c4e8dbc 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -92,6 +92,7 @@ struct _virNetServer {
virNetServerClientPtr *clients; /* Clients */
size_t nclients_max; /* Max allowed clients count */
size_t nclients_unauth; /* Unauthenticated clients count */
+ size_t nclients_unauth_max; /* Max allowed unauth clients count */
int keepaliveInterval;
unsigned int keepaliveCount;
@@ -279,6 +280,14 @@ static int virNetServerAddClient(virNetServerPtr srv,
if (virNetServerClientNeedAuth(client))
virNetServerClientAuthLocked(srv, true);
+ if (srv->nclients_unauth_max &&
+ srv->nclients_unauth == srv->nclients_unauth_max) {
+ /* Temporarily stop accepting new clients */
+ VIR_DEBUG("Temporarily suspending services "
+ "due to max_anonymous_clients");
+ virNetServerUpdateServicesLocked(srv, false);
+ }
+
if (srv->nclients == srv->nclients_max) {
/* Temporarily stop accepting new clients */
VIR_DEBUG("Temporarily suspending services due to max_clients");
@@ -362,6 +371,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers,
size_t priority_workers,
size_t max_clients,
+ size_t max_anonymous_clients,
int keepaliveInterval,
unsigned int keepaliveCount,
bool keepaliveRequired,
@@ -388,6 +398,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
goto error;
srv->nclients_max = max_clients;
+ srv->nclients_unauth_max = max_anonymous_clients;
srv->keepaliveInterval = keepaliveInterval;
srv->keepaliveCount = keepaliveCount;
srv->keepaliveRequired = keepaliveRequired;
@@ -457,6 +468,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr
object,
unsigned int max_workers;
unsigned int priority_workers;
unsigned int max_clients;
+ unsigned int nclients_unauth_max;
unsigned int keepaliveInterval;
unsigned int keepaliveCount;
bool keepaliveRequired;
@@ -482,6 +494,11 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr
object,
_("Missing max_clients data in JSON document"));
goto error;
}
+ if (virJSONValueObjectGetNumberUint(object, "nclients_unauth_max",
&nclients_unauth_max) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing nclients_unauth_max data in JSON
document"));
+ goto error;
+ }
if (virJSONValueObjectGetNumberUint(object, "keepaliveInterval",
&keepaliveInterval) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing keepaliveInterval data in JSON document"));
@@ -507,6 +524,7 @@ virNetServerPtr virNetServerNewPostExecRestart(virJSONValuePtr
object,
if (!(srv = virNetServerNew(min_workers, max_clients,
priority_workers, max_clients,
+ nclients_unauth_max,
keepaliveInterval, keepaliveCount,
keepaliveRequired, mdnsGroupName,
clientPrivNew, clientPrivPreExecRestart,
@@ -625,6 +643,12 @@ virJSONValuePtr virNetServerPreExecRestart(virNetServerPtr srv)
_("Cannot set max_clients data in JSON document"));
goto error;
}
+ if (virJSONValueObjectAppendNumberUint(object, "nclients_unauth_max",
+ srv->nclients_unauth_max) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot set nclients_unauth_max data in JSON
document"));
+ goto error;
+ }
if (virJSONValueObjectAppendNumberUint(object, "keepaliveInterval",
srv->keepaliveInterval) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot set keepaliveInterval data in JSON
document"));
@@ -1150,8 +1174,17 @@ void virNetServerRun(virNetServerPtr srv)
virNetServerClientAuthLocked(srv, false);
/* Enable services if we can accept a new client.
- * The new client can be accepted if we are at the limit. */
- if (srv->nclients == srv->nclients_max - 1) {
+ * The new client can be accepted if both max_clients and
+ * max_anonymous_clients wouldn't get overcommitted by
+ * accepting it. */
+ VIR_DEBUG("Considering re-enabling services: "
+ "nclients=%zu nclients_max=%zu "
+ "nclients_unauth=%zu nclients_unauth_max=%zu",
+ srv->nclients, srv->nclients_max,
+ srv->nclients_unauth, srv->nclients_unauth_max);
+ if (srv->nclients < srv->nclients_max &&
+ (!srv->nclients_unauth_max ||
+ srv->nclients_unauth < srv->nclients_unauth_max)) {
/* Now it makes sense to accept() a new client. */
VIR_DEBUG("Re-enabling services");
virNetServerUpdateServicesLocked(srv, true);
@@ -1262,7 +1295,22 @@ size_t virNetServerClientAuth(virNetServerPtr srv,
{
size_t ret;
virObjectLock(srv);
+
ret = virNetServerClientAuthLocked(srv, need_auth);
+
+ VIR_DEBUG("Considering re-enabling services: "
+ "nclients=%zu nclients_max=%zu "
+ "nclients_unauth=%zu nclients_unauth_max=%zu",
+ srv->nclients, srv->nclients_max,
+ srv->nclients_unauth, srv->nclients_unauth_max);
+ if (srv->nclients < srv->nclients_max &&
+ (!srv->nclients_unauth_max ||
+ srv->nclients_unauth < srv->nclients_unauth_max)) {
+ /* Now it makes sense to accept() a new client. */
+ VIR_DEBUG("Re-enabling services");
+ virNetServerUpdateServicesLocked(srv, true);
+ }
+
virObjectUnlock(srv);
return ret;
}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 703a733..4b165c3 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -39,6 +39,7 @@ virNetServerPtr virNetServerNew(size_t min_workers,
size_t max_workers,
size_t priority_workers,
size_t max_clients,
+ size_t max_anonymous_clients,
int keepaliveInterval,
unsigned int keepaliveCount,
bool keepaliveRequired,
--
1.9.0