Skip to content

Commit

Permalink
Add admin-port feature
Browse files Browse the repository at this point in the history
Signed-off-by: hwware <[email protected]>
  • Loading branch information
hwware committed Oct 7, 2024
1 parent b5eb793 commit bccac8c
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,7 @@ standardConfig static_configs[] = {
/* Integer configs */
createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL),
createIntConfig("port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.port, 6379, INTEGER_CONFIG, NULL, updatePort), /* TCP port. */
createIntConfig("admin-port", NULL, IMMUTABLE_CONFIG, 0, 65535, server.admin_port, 0, INTEGER_CONFIG, NULL, NULL), /* TCP admin port. */
createIntConfig("io-threads", NULL, DEBUG_CONFIG | IMMUTABLE_CONFIG, 1, 128, server.io_threads_num, 1, INTEGER_CONFIG, NULL, NULL), /* Single threaded by default */
createIntConfig("events-per-io-thread", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.events_per_io_thread, 2, INTEGER_CONFIG, NULL, NULL),
createIntConfig("prefetch-batch-max-size", NULL, MODIFIABLE_CONFIG, 0, 128, server.prefetch_batch_max_size, 16, INTEGER_CONFIG, NULL, NULL),
Expand Down
17 changes: 16 additions & 1 deletion src/networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,7 @@ void clientAcceptHandler(connection *conn) {
void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
client *c;
UNUSED(ip);
int port;

if (connGetState(conn) != CONN_STATE_ACCEPTING) {
char addr[NET_ADDR_STR_LEN] = {0};
Expand All @@ -1401,12 +1402,26 @@ void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
return;
}

if (connAddrSockName(conn, NULL, 0, &port)) {
serverLog(LL_WARNING, "Unable to retrieve socket port");
connClose(conn);
return;
}

if (port == server.admin_port && connIsLocal(conn) != 1) {
serverLog(LL_WARNING, "Denied connection. On admin-port, connections are"
" only accepted from the loopback interface.");
server.stat_rejected_conn++;
connClose(conn);
return;
}

/* Limit the number of connections we take at the same time.
*
* Admission control will happen before a client is created and connAccept()
* called, because we don't want to even start transport-level negotiation
* if rejected. */
if (listLength(server.clients) + getClusterConnectionsCount() >= server.maxclients) {
if (port != server.admin_port && (listLength(server.clients) + getClusterConnectionsCount() >= server.maxclients)) {
char *err;
if (server.cluster_enabled)
err = "-ERR max number of clients + cluster "
Expand Down
19 changes: 19 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,25 @@ void initListeners(void) {
listener->priv2 = server.unixsocketgroup; /* Unix socket group specified */
}

if (server.admin_port != 0) {
conn_index = connectionIndexByType(CONN_TYPE_SOCKET);
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_SOCKET);

// Check if the current index is already occupied
while (server.listeners[conn_index].ct != NULL) {
conn_index++;
if (conn_index >= CONN_TYPE_MAX) {
serverPanic("No available index for additional TCP listener.");
}
}

listener = &server.listeners[conn_index];
listener->bindaddr = server.bindaddr;
listener->bindaddr_count = server.bindaddr_count;
listener->port = server.admin_port;
listener->ct = connectionByType(CONN_TYPE_SOCKET);
}

/* create all the configured listener, and add handler to start to accept */
int listen_fds = 0;
for (int j = 0; j < CONN_TYPE_MAX; j++) {
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,7 @@ struct valkeyServer {
_Atomic int module_gil_acquiring; /* Indicates whether the GIL is being acquiring by the main thread. */
/* Networking */
int port; /* TCP listening port */
int admin_port; /* TCP listening admin port */
int tls_port; /* TLS listening port */
int tcp_backlog; /* TCP listen() backlog */
char *bindaddr[CONFIG_BINDADDR_MAX]; /* Addresses we should bind to */
Expand Down
9 changes: 8 additions & 1 deletion tests/support/server.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,9 @@ proc start_server {options {code undefined}} {
dict set config "tls-cluster" "yes"
dict set config "tls-replication" "yes"
} else {
dict set config port $port
set aport [find_available_port $::baseport $::portcount]
dict set config "port" $port
dict set config "admin-port" $aport
}

set unixsocket [file normalize [format "%s/%s" [dict get $config "dir"] "socket"]]
Expand Down Expand Up @@ -604,7 +606,9 @@ proc start_server {options {code undefined}} {
dict set config port $pport
dict set config "tls-port" $port
} else {
set aport [find_available_port $::baseport $::portcount]
dict set config port $port
dict set config admin-port $aport
}
create_server_config_file $config_file $config $config_lines

Expand Down Expand Up @@ -638,15 +642,18 @@ proc start_server {options {code undefined}} {
# setup properties to be able to initialize a client object
set port_param [expr $::tls ? {"tls-port"} : {"port"}]
set host $::host
set admin_port 0
if {[dict exists $config bind]} { set host [lindex [dict get $config bind] 0] }
if {[dict exists $config $port_param]} { set port [dict get $config $port_param] }
if {[dict exists $config admin-port]} { set admin_port [lindex [dict get $config admin-port] 0] }

# setup config dict
dict set srv "config_file" $config_file
dict set srv "config" $config
dict set srv "pid" $pid
dict set srv "host" $host
dict set srv "port" $port
dict set srv "admin-port" $admin_port
dict set srv "stdout" $stdout
dict set srv "stderr" $stderr
dict set srv "unixsocket" $unixsocket
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/admin-port.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
tags {external:skip tls:skip} {
test {admin-port: CONFIG SET port number should fail} {
start_server {} {
set avail_port [find_available_port $::baseport $::portcount]
set rd [valkey [srv 0 host] [srv 0 admin-port]]
assert_error {*can't set immutable config*} {$rd CONFIG SET admin-port $avail_port}
$rd PING
$rd close
}
}

test {admin-port: connection should fail on non-loopback interface} {
start_server {} {
catch {valkey [get_nonloopback_addr] [srv 0 admin-port]} e
assert_match {*connection refused*} $e
}
}

test {admin-port: setting admin-port to server port should fail} {
start_server {} {
catch {r CONFIG SET port [srv 0 admin-port]} e
assert_match {*Unable to listen on this port*} $e
}
}

test {admin-port: client could connect on admin-port after maxclients reached} {
start_server {} {
set original_maxclients [lindex [r config get maxclients] 1]
r config set maxclients 2
set rd [valkey [srv 0 host] [srv 0 port]]
assert_match "PONG" [$rd PING]
set rd1 [valkey [srv 0 host] [srv 0 port]]
catch {$rd1 PING} e
assert_match "*ERR max*reached*" $e
set rd2 [valkey [srv 0 host] [srv 0 admin-port]]
assert_match "PONG" [$rd2 PING]
r config set maxclients $original_maxclients
$rd close
$rd1 close
$rd2 close
}
}
}
1 change: 1 addition & 0 deletions tests/unit/introspection.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ start_server {tags {"introspection"}} {
req-res-logfile
client-default-resp
dual-channel-replication-enabled
admin-port
}

if {!$::tls} {
Expand Down
9 changes: 9 additions & 0 deletions valkey.conf
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ protected-mode yes
# If port 0 is specified the server will not listen on a TCP socket.
port 6379

# admin-port
#
# Accept connections on the specified port and connections should be originating from
# local loopback (127.0.0.1), unix domain socket or IPv6 address (::1).
# Default is 0 and immutable.
# If admin-port is not specified the server will not listen on a TCP socket.
#
# admin-port 0

# TCP listen() backlog.
#
# In high requests-per-second environments you need a high backlog in order
Expand Down

0 comments on commit bccac8c

Please sign in to comment.