summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redis.conf10
-rw-r--r--src/anet.c17
-rw-r--r--src/anet.h1
-rw-r--r--src/config.c1
-rw-r--r--src/config.h18
-rw-r--r--src/server.c1
-rw-r--r--src/server.h1
-rw-r--r--tests/unit/introspection.tcl1
8 files changed, 50 insertions, 0 deletions
diff --git a/redis.conf b/redis.conf
index 4fbbaf7e0..d2074f13f 100644
--- a/redis.conf
+++ b/redis.conf
@@ -175,6 +175,16 @@ timeout 0
# Redis default starting with Redis 3.2.1.
tcp-keepalive 300
+# Apply OS-specific mechanism to mark the listening socket with the specified
+# ID, to support advanced routing and filtering capabilities.
+#
+# On Linux, the ID represents a connection mark.
+# On FreeBSD, the ID represents a socket cookie ID.
+# On OpenBSD, the ID represents a route table ID.
+#
+# The default value is 0, which implies no marking is required.
+# socket-mark-id 0
+
################################# TLS/SSL #####################################
# By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration
diff --git a/src/anet.c b/src/anet.c
index bde460fc8..3ded135b0 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -49,6 +49,8 @@
#include "anet.h"
#include "config.h"
+#define UNUSED(x) (void)(x)
+
static void anetSetError(char *err, const char *fmt, ...)
{
va_list ap;
@@ -680,3 +682,18 @@ error:
close(fds[1]);
return -1;
}
+
+int anetSetSockMarkId(char *err, int fd, uint32_t id) {
+#ifdef HAVE_SOCKOPTMARKID
+ if (setsockopt(fd, SOL_SOCKET, SOCKOPTMARKID, (void *)&id, sizeof(id)) == -1) {
+ anetSetError(err, "setsockopt: %s", strerror(errno));
+ return ANET_ERR;
+ }
+ return ANET_OK;
+#else
+ UNUSED(fd);
+ UNUSED(id);
+ anetSetError(err,"anetSetSockMarkid unsupported on this platform");
+ return ANET_OK;
+#endif
+}
diff --git a/src/anet.h b/src/anet.h
index 96238aaf4..ff86e2029 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -73,5 +73,6 @@ int anetKeepAlive(char *err, int fd, int interval);
int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type);
int anetPipe(int fds[2], int read_flags, int write_flags);
+int anetSetSockMarkId(char *err, int fd, uint32_t id);
#endif
diff --git a/src/config.c b/src/config.c
index c4b893c28..d5e347892 100644
--- a/src/config.c
+++ b/src/config.c
@@ -2977,6 +2977,7 @@ standardConfig static_configs[] = {
/* Unsigned int configs */
createUIntConfig("maxclients", NULL, MODIFIABLE_CONFIG, 1, UINT_MAX, server.maxclients, 10000, INTEGER_CONFIG, NULL, updateMaxclients),
createUIntConfig("unixsocketperm", NULL, IMMUTABLE_CONFIG, 0, 0777, server.unixsocketperm, 0, OCTAL_CONFIG, NULL, NULL),
+ createUIntConfig("socket-mark-id", NULL, IMMUTABLE_CONFIG, 0, UINT_MAX, server.socket_mark_id, 0, INTEGER_CONFIG, NULL, NULL),
/* Unsigned Long configs */
createULongConfig("active-defrag-max-scan-fields", NULL, MODIFIABLE_CONFIG, 1, LONG_MAX, server.active_defrag_max_scan_fields, 1000, INTEGER_CONFIG, NULL, NULL), /* Default: keys with more than 1000 fields will be processed separately */
diff --git a/src/config.h b/src/config.h
index 210e55a87..6baa8bd0f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -80,6 +80,10 @@
/* MSG_NOSIGNAL. */
#ifdef __linux__
#define HAVE_MSG_NOSIGNAL 1
+#if defined(SO_MARK)
+#define HAVE_SOCKOPTMARKID 1
+#define SOCKOPTMARKID SO_MARK
+#endif
#endif
/* Test for polling API */
@@ -113,6 +117,20 @@
#define redis_fsync(fd) fsync(fd)
#endif
+#if defined(__FreeBSD__)
+#if defined(SO_USER_COOKIE)
+#define HAVE_SOCKOPTMARKID 1
+#define SOCKOPTMARKID SO_USER_COOKIE
+#endif
+#endif
+
+#if defined(__OpenBSD__)
+#if defined(SO_RTABLE)
+#define HAVE_SOCKOPTMARKID 1
+#define SOCKOPTMARKID SO_RTABLE
+#endif
+#endif
+
#if __GNUC__ >= 4
#define redis_unreachable __builtin_unreachable
#else
diff --git a/src/server.c b/src/server.c
index f632279fa..285ed8963 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2293,6 +2293,7 @@ int listenToPort(int port, socketFds *sfd) {
closeSocketListeners(sfd);
return C_ERR;
}
+ if (server.socket_mark_id > 0) anetSetSockMarkId(NULL, sfd->fd[sfd->count], server.socket_mark_id);
anetNonBlock(NULL,sfd->fd[sfd->count]);
anetCloexec(sfd->fd[sfd->count]);
sfd->count++;
diff --git a/src/server.h b/src/server.h
index b57f39d38..ace9f1219 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1494,6 +1494,7 @@ struct redisServer {
socketFds ipfd; /* TCP socket file descriptors */
socketFds tlsfd; /* TLS socket file descriptors */
int sofd; /* Unix socket file descriptor */
+ uint32_t socket_mark_id; /* ID for listen socket marking */
socketFds cfd; /* Cluster bus listening socket */
list *clients; /* List of active clients */
list *clients_to_close; /* Clients to close asynchronously */
diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl
index 339d4c731..89d8f170b 100644
--- a/tests/unit/introspection.tcl
+++ b/tests/unit/introspection.tcl
@@ -215,6 +215,7 @@ start_server {tags {"introspection"}} {
dbfilename
logfile
dir
+ socket-mark-id
}
if {!$::tls} {