Skip to content

Commit 83bc4a3

Browse files
committed
Introduce RDMA transport (experimental)
Valkey Over RDMA[1] has been supported as experimental feature since Valkey 8.0. Support RDMA transport for the client side. RDMA is not a builtin feature, supported as module only, so we have to run test.sh with more argument @VALKEY_RDMA_MODULE and @VALKEY_RDMA_ADDR. An example to run test.sh: VALKEY_RDMA_MODULE=/path/to/valkey-rdma.so VALKEY_RDMA_ADDR=192.168.122.1 TEST_RDMA=1 ./test.sh ... Testing against RDMA connection (192.168.122.1:56379): #138 Is able to deliver commands: PASSED #139 Is a able to send commands verbatim: PASSED #140 %s String interpolation works: PASSED #141 %b String interpolation works: PASSED #142 Binary reply length is correct: PASSED #143 Can parse nil replies: PASSED #144 Can parse integer replies: PASSED #145 Can parse multi bulk replies: PASSED #146 Can handle nested multi bulk replies: PASSED #147 Send command by passing argc/argv: PASSED #148 Can pass NULL to valkeyGetReply: PASSED #149 RESP3 PUSH messages are handled out of band by default: PASSED #150 We can set a custom RESP3 PUSH handler: PASSED #151 We properly handle a NIL invalidation payload: PASSED #152 With no handler, PUSH replies come in-band: PASSED #153 With no PUSH handler, no replies are lost: PASSED #154 We set a default RESP3 handler for valkeyContext: PASSED #155 We don't set a default RESP3 push handler for valkeyAsyncContext: PASSED #156 Our VALKEY_OPT_NO_PUSH_AUTOFREE flag works: PASSED #157 We can use valkeyOptions to set a custom PUSH handler for valkeyContext: PASSED #158 We can use valkeyOptions to set a custom PUSH handler for valkeyAsyncContext: PASSED #159 We can use valkeyOptions to set privdata: PASSED #160 Our privdata destructor fires when we free the context: PASSED #161 Successfully completes a command when the timeout is not exceeded: PASSED #162 Does not return a reply when the command times out: SKIPPED #163 Reconnect properly reconnects after a timeout: PASSED #164 Reconnect properly uses owned parameters: PASSED #165 Returns I/O error when the connection is lost: PASSED #166 Returns I/O error on socket timeout: PASSED #167 Set error when an invalid timeout usec value is used during connect: PASSED #168 Set error when an invalid timeout sec value is used during connect: PASSED #169 Append format command: PASSED #170 Throughput: (1000x PING: 0.010s) (1000x LRANGE with 500 elements: 0.060s) (1000x INCRBY: 0.012s) (10000x PING (pipelined): 0.066s) (10000x LRANGE with 500 elements (pipelined): 0.523s) (10000x INCRBY (pipelined): 0.024s) ... Link[1]: valkey-io/valkey#477 Signed-off-by: zhenwei pi <[email protected]>
1 parent 82ca44e commit 83bc4a3

File tree

8 files changed

+1188
-10
lines changed

8 files changed

+1188
-10
lines changed

Makefile

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ INCLUDE_DIR = include/valkey
1515
TEST_SRCS = $(TEST_DIR)/client_test.c
1616
TEST_BINS = $(patsubst $(TEST_DIR)/%.c,$(TEST_DIR)/%,$(TEST_SRCS))
1717

18-
SOURCES = $(filter-out $(wildcard $(SRC_DIR)/*ssl*.c), $(wildcard $(SRC_DIR)/*.c))
19-
HEADERS = $(filter-out $(INCLUDE_DIR)/valkey_ssl.h, $(wildcard $(INCLUDE_DIR)/*.h))
18+
SOURCES = $(filter-out $(wildcard $(SRC_DIR)/*ssl*.c, wildcard $(SRC_DIR)/*rdma*.c), $(wildcard $(SRC_DIR)/*.c))
19+
HEADERS = $(filter-out $(INCLUDE_DIR)/valkey_ssl.h $(INCLUDE_DIR)/valkey_rdma.h, $(wildcard $(INCLUDE_DIR)/*.h))
2020

2121
OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SOURCES))
2222

@@ -25,6 +25,7 @@ PKGCONFNAME=$(LIB_DIR)/valkey.pc
2525

2626
PKGCONF_TEMPLATE = valkey.pc.in
2727
SSL_PKGCONF_TEMPLATE = valkey_ssl.pc.in
28+
RDMA_PKGCONF_TEMPLATE = valkey_rdma.pc.in
2829

2930
LIBVALKEY_HEADER=$(INCLUDE_DIR)/valkey.h
3031
LIBVALKEY_VERSION=$(shell awk '/LIBVALKEY_(MAJOR|MINOR|PATCH|SONAME)/{print $$3}' $(LIBVALKEY_HEADER))
@@ -111,6 +112,38 @@ else
111112
endif
112113
##################### SSL variables end #####################
113114

115+
#################### RDMA variables start ####################
116+
RDMA_LIBNAME=libvalkey_rdma
117+
RDMA_PKGCONFNAME=$(LIB_DIR)/valkey_rdma.pc
118+
RDMA_INSTALLNAME=install-rdma
119+
RDMA_DYLIB_MINOR_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX).$(LIBVALKEY_SONAME)
120+
RDMA_DYLIB_MAJOR_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX).$(LIBVALKEY_MAJOR)
121+
RDMA_ROOT_DYLIB_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX)
122+
RDMA_DYLIBNAME=$(LIB_DIR)/$(RDMA_LIBNAME).$(DYLIBSUFFIX)
123+
RDMA_STLIBNAME=$(LIB_DIR)/$(RDMA_LIBNAME).$(STLIBSUFFIX)
124+
RDMA_DYLIB_MAKE_CMD=$(CC) $(OPTIMIZATION) $(PLATFORM_FLAGS) -shared -Wl,-soname,$(RDMA_DYLIB_MINOR_NAME)
125+
126+
USE_RDMA?=0
127+
128+
ifeq ($(USE_RDMA),1)
129+
RDMA_SOURCES = $(wildcard $(SRC_DIR)/*rdma*.c)
130+
RDMA_OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(RDMA_SOURCES))
131+
132+
RDMA_LDFLAGS+=-lrdmacm -libverbs
133+
# This is required for test.c only
134+
CFLAGS+=-DVALKEY_TEST_RDMA
135+
RDMA_STLIB=$(RDMA_STLIBNAME)
136+
RDMA_DYLIB=$(RDMA_DYLIBNAME)
137+
RDMA_PKGCONF=$(RDMA_PKGCONFNAME)
138+
RDMA_INSTALL=$(RDMA_INSTALLNAME)
139+
else
140+
RDMA_STLIB=
141+
RDMA_DYLIB=
142+
RDMA_PKGCONF=
143+
RDMA_INSTALL=
144+
endif
145+
##################### RDMA variables end #####################
146+
114147
# Platform-specific overrides
115148
uname_S := $(shell uname -s 2>/dev/null || echo not)
116149

@@ -174,30 +207,37 @@ $(SSL_DYLIBNAME): $(SSL_OBJS)
174207
$(SSL_STLIBNAME): $(SSL_OBJS)
175208
$(STLIB_MAKE_CMD) $(SSL_STLIBNAME) $(SSL_OBJS)
176209

210+
$(RDMA_DYLIBNAME): $(RDMA_OBJS)
211+
$(RDMA_DYLIB_MAKE_CMD) $(DYLIB_PLUGIN) -o $(RDMA_DYLIBNAME) $(RDMA_OBJS) $(REAL_LDFLAGS) $(LDFLAGS) $(RDMA_LDFLAGS)
212+
213+
$(RDMA_STLIBNAME): $(RDMA_OBJS)
214+
$(STLIB_MAKE_CMD) $(RDMA_STLIBNAME) $(RDMA_OBJS)
215+
216+
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
177217
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
178218
$(CC) -std=c99 -pedantic $(REAL_CFLAGS) -I$(INCLUDE_DIR) -MMD -MP -c $< -o $@
179219

180220
$(OBJ_DIR)/%.o: $(TEST_DIR)/%.c | $(OBJ_DIR)
181221
$(CC) -std=c99 -pedantic $(REAL_CFLAGS) -I$(INCLUDE_DIR) -MMD -MP -c $< -o $@
182222

183223
$(TEST_DIR)/%: $(OBJ_DIR)/%.o $(STLIBNAME)
184-
$(CC) -o $@ $< $(STLIBNAME) $(SSL_STLIB) $(LDFLAGS) $(TEST_LDFLAGS)
224+
$(CC) -o $@ $< $(RDMA_STLIB) $(STLIBNAME) $(SSL_STLIB) $(LDFLAGS) $(TEST_LDFLAGS)
185225

186226
$(OBJ_DIR):
187227
mkdir -p $(OBJ_DIR)
188228

189229
$(LIB_DIR):
190230
mkdir -p $(LIB_DIR)
191231

192-
dynamic: $(DYLIBNAME) $(SSL_DYLIB)
232+
dynamic: $(DYLIBNAME) $(SSL_DYLIB) $(RDMA_DYLIB)
193233

194-
static: $(STLIBNAME) $(SSL_STLIB)
234+
static: $(STLIBNAME) $(SSL_STLIB) $(RDMA_STLIB)
195235

196-
pkgconfig: $(PKGCONFNAME) $(SSL_PKGCONF)
236+
pkgconfig: $(PKGCONFNAME) $(SSL_PKGCONF) $(RDMA_PKGCONF)
197237

198238
-include $(OBJS:.o=.d)
199239

200-
TEST_LDFLAGS = $(SSL_LDFLAGS)
240+
TEST_LDFLAGS = $(SSL_LDFLAGS) $(RDMA_LDFLAGS)
201241
ifeq ($(USE_SSL),1)
202242
TEST_LDFLAGS += -pthread
203243
endif
@@ -232,6 +272,14 @@ $(SSL_PKGCONFNAME): $(SSL_PKGCONF_TEMPLATE)
232272
-e 's|@PROJECT_VERSION@|$(LIBVALKEY_SONAME)|g' \
233273
$< > $@
234274

275+
$(RDMA_PKGCONFNAME): $(RDMA_PKGCONF_TEMPLATE)
276+
@echo "Generating $@ for pkgconfig..."
277+
sed \
278+
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|g' \
279+
-e 's|@CMAKE_INSTALL_LIBDIR@|$(INSTALL_LIBRARY_PATH)|g' \
280+
-e 's|@PROJECT_VERSION@|$(LIBVALKEY_SONAME)|g' \
281+
$< > $@
282+
235283
install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) $(SSL_INSTALL)
236284
mkdir -p $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH)
237285
$(INSTALL) $(HEADERS) $(INSTALL_INCLUDE_PATH)
@@ -253,6 +301,16 @@ install-ssl: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME)
253301
mkdir -p $(INSTALL_PKGCONF_PATH)
254302
$(INSTALL) $(SSL_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
255303

304+
install-rdma: $(RDMA_DYLIBNAME) $(RDMA_STLIBNAME) $(RDMA_PKGCONFNAME)
305+
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
306+
$(INSTALL) $(INCLUDE_DIR)/valkey_rdma.h $(INSTALL_INCLUDE_PATH)
307+
$(INSTALL) $(RDMA_DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_DYLIB_MINOR_NAME)
308+
ln -sf $(RDMA_DYLIB_MINOR_NAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_ROOT_DYLIB_NAME)
309+
ln -sf $(RDMA_DYLIB_MINOR_NAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_DYLIB_MAJOR_NAME)
310+
$(INSTALL) $(RDMA_STLIBNAME) $(INSTALL_LIBRARY_PATH)
311+
mkdir -p $(INSTALL_PKGCONF_PATH)
312+
$(INSTALL) $(RDMA_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
313+
256314
32bit:
257315
@echo ""
258316
@echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"

include/valkey/valkey.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ enum valkeyConnectionType {
148148
VALKEY_CONN_TCP,
149149
VALKEY_CONN_UNIX,
150150
VALKEY_CONN_USERFD,
151+
VALKEY_CONN_RDMA, /* experimental, may be removed in any version */
151152

152153
VALKEY_CONN_MAX
153154
};

include/valkey/valkey_rdma.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
/*
3+
* Copyright (c) 2021-2024 zhenwei pi <[email protected]>
4+
*
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* * Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
* * Neither the name of Redis nor the names of its contributors may be used
16+
* to endorse or promote products derived from this software without
17+
* specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
* POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
#ifndef VALKEY_RDMA_H
33+
#define VALKEY_RDMA_H
34+
35+
#ifdef __cplusplus
36+
extern "C" {
37+
#endif
38+
39+
/**
40+
* Helper macros to initialize options for RDMA.
41+
* It's ok to reuse TCP options.
42+
*/
43+
#define VALKEY_OPTIONS_SET_RDMA(opts, ip_, port_) do { \
44+
(opts)->type = VALKEY_CONN_RDMA; \
45+
(opts)->endpoint.tcp.ip = ip_; \
46+
(opts)->endpoint.tcp.port = port_; \
47+
} while(0)
48+
49+
50+
int valkeyInitiateRdma(void);
51+
52+
#ifdef __cplusplus
53+
}
54+
#endif
55+
56+
#endif /* VALKEY_RDMA_H */

0 commit comments

Comments
 (0)