Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce RDMA transport (experimental) #55

Merged
merged 4 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ OPTION(DISABLE_TESTS "If tests should be compiled or not" OFF)
OPTION(ENABLE_EXAMPLES "Enable building valkey examples" OFF)
option(ENABLE_IPV6_TESTS "Enable IPv6 tests requiring special prerequisites" OFF)
OPTION(ENABLE_NUGET "Install NuGET packaging details" OFF)
OPTION(ENABLE_RDMA "Build valkey_rdma for RDMA support" OFF)

# valkey requires C99
SET(CMAKE_C_STANDARD 99)
Expand All @@ -33,6 +34,7 @@ SET(valkey_sources
src/alloc.c
src/async.c
src/command.c
src/conn.c
src/crc16.c
src/dict.c
src/net.c
Expand Down Expand Up @@ -226,6 +228,53 @@ IF(ENABLE_SSL)
DESTINATION ${CMAKE_CONF_INSTALL_DIR})
ENDIF()

if(ENABLE_RDMA)
find_library(RDMACM_LIBRARIES rdmacm)
find_library(IBVERBS_LIBRARIES ibverbs)
set(valkey_rdma_sources src/rdma.c)
add_library(valkey_rdma ${valkey_rdma_sources})
add_library(valkey::valkey_rdma ALIAS valkey_rdma)

target_link_libraries(valkey_rdma LINK_PRIVATE ${RDMACM_LIBRARIES} ${IBVERBS_LIBRARIES})
target_include_directories(valkey_rdma
PRIVATE
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/valkey>
)

set_target_properties(valkey_rdma
PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS TRUE
pizhenwei marked this conversation as resolved.
Show resolved Hide resolved
VERSION "${LIBVALKEY_SONAME}")
configure_file(valkey_rdma.pc.in valkey_rdma.pc @ONLY)

install(TARGETS valkey_rdma
EXPORT valkey_rdma-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/valkey_rdma.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

export(EXPORT valkey_rdma-targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/valkey_rdma-targets.cmake"
NAMESPACE valkey::)

set(CMAKE_CONF_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/valkey_rdma)
configure_package_config_file(valkey_rdma-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/valkey_rdma-config.cmake
INSTALL_DESTINATION ${CMAKE_CONF_INSTALL_DIR}
PATH_VARS INCLUDE_INSTALL_DIR)

install(EXPORT valkey_rdma-targets
FILE valkey_rdma-targets.cmake
NAMESPACE valkey::
DESTINATION ${CMAKE_CONF_INSTALL_DIR})

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/valkey_rdma-config.cmake
DESTINATION ${CMAKE_CONF_INSTALL_DIR})
endif()

# Add tests
if(NOT DISABLE_TESTS)
# Make sure ctest prints the output when a test fails.
Expand Down
71 changes: 64 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ INCLUDE_DIR = include/valkey
TEST_SRCS = $(TEST_DIR)/client_test.c
TEST_BINS = $(patsubst $(TEST_DIR)/%.c,$(TEST_DIR)/%,$(TEST_SRCS))

SOURCES = $(filter-out $(wildcard $(SRC_DIR)/*ssl*.c), $(wildcard $(SRC_DIR)/*.c))
HEADERS = $(filter-out $(INCLUDE_DIR)/valkey_ssl.h, $(wildcard $(INCLUDE_DIR)/*.h))
SOURCES = $(filter-out $(wildcard $(SRC_DIR)/*ssl*.c, wildcard $(SRC_DIR)/*rdma*.c), $(wildcard $(SRC_DIR)/*.c))
pizhenwei marked this conversation as resolved.
Show resolved Hide resolved
HEADERS = $(filter-out $(INCLUDE_DIR)/valkey_ssl.h $(INCLUDE_DIR)/valkey_rdma.h, $(wildcard $(INCLUDE_DIR)/*.h))

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

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

PKGCONF_TEMPLATE = valkey.pc.in
SSL_PKGCONF_TEMPLATE = valkey_ssl.pc.in
RDMA_PKGCONF_TEMPLATE = valkey_rdma.pc.in

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

#################### RDMA variables start ####################
RDMA_LIBNAME=libvalkey_rdma
RDMA_PKGCONFNAME=$(LIB_DIR)/valkey_rdma.pc
RDMA_INSTALLNAME=install-rdma
RDMA_DYLIB_MINOR_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX).$(LIBVALKEY_SONAME)
RDMA_DYLIB_MAJOR_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX).$(LIBVALKEY_MAJOR)
RDMA_ROOT_DYLIB_NAME=$(RDMA_LIBNAME).$(DYLIBSUFFIX)
RDMA_DYLIBNAME=$(LIB_DIR)/$(RDMA_LIBNAME).$(DYLIBSUFFIX)
RDMA_STLIBNAME=$(LIB_DIR)/$(RDMA_LIBNAME).$(STLIBSUFFIX)
RDMA_DYLIB_MAKE_CMD=$(CC) $(OPTIMIZATION) $(PLATFORM_FLAGS) -shared -Wl,-soname,$(RDMA_DYLIB_MINOR_NAME)

USE_RDMA?=0

ifeq ($(USE_RDMA),1)
RDMA_SOURCES = $(wildcard $(SRC_DIR)/*rdma*.c)
RDMA_OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(RDMA_SOURCES))

RDMA_LDFLAGS+=-lrdmacm -libverbs
# This is required for test.c only
CFLAGS+=-DVALKEY_TEST_RDMA
RDMA_STLIB=$(RDMA_STLIBNAME)
RDMA_DYLIB=$(RDMA_DYLIBNAME)
RDMA_PKGCONF=$(RDMA_PKGCONFNAME)
RDMA_INSTALL=$(RDMA_INSTALLNAME)
else
RDMA_STLIB=
RDMA_DYLIB=
RDMA_PKGCONF=
RDMA_INSTALL=
endif
##################### RDMA variables end #####################

# Platform-specific overrides
uname_S := $(shell uname -s 2>/dev/null || echo not)

Expand Down Expand Up @@ -174,30 +207,36 @@ $(SSL_DYLIBNAME): $(SSL_OBJS)
$(SSL_STLIBNAME): $(SSL_OBJS)
$(STLIB_MAKE_CMD) $(SSL_STLIBNAME) $(SSL_OBJS)

$(RDMA_DYLIBNAME): $(RDMA_OBJS)
$(RDMA_DYLIB_MAKE_CMD) $(DYLIB_PLUGIN) -o $(RDMA_DYLIBNAME) $(RDMA_OBJS) $(REAL_LDFLAGS) $(LDFLAGS) $(RDMA_LDFLAGS)

$(RDMA_STLIBNAME): $(RDMA_OBJS)
$(STLIB_MAKE_CMD) $(RDMA_STLIBNAME) $(RDMA_OBJS)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
pizhenwei marked this conversation as resolved.
Show resolved Hide resolved
$(CC) -std=c99 -pedantic $(REAL_CFLAGS) -I$(INCLUDE_DIR) -MMD -MP -c $< -o $@

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

$(TEST_DIR)/%: $(OBJ_DIR)/%.o $(STLIBNAME)
$(CC) -o $@ $< $(STLIBNAME) $(SSL_STLIB) $(LDFLAGS) $(TEST_LDFLAGS)
$(CC) -o $@ $< $(RDMA_STLIB) $(STLIBNAME) $(SSL_STLIB) $(LDFLAGS) $(TEST_LDFLAGS)

$(OBJ_DIR):
mkdir -p $(OBJ_DIR)

$(LIB_DIR):
mkdir -p $(LIB_DIR)

dynamic: $(DYLIBNAME) $(SSL_DYLIB)
dynamic: $(DYLIBNAME) $(SSL_DYLIB) $(RDMA_DYLIB)

static: $(STLIBNAME) $(SSL_STLIB)
static: $(STLIBNAME) $(SSL_STLIB) $(RDMA_STLIB)

pkgconfig: $(PKGCONFNAME) $(SSL_PKGCONF)
pkgconfig: $(PKGCONFNAME) $(SSL_PKGCONF) $(RDMA_PKGCONF)

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

TEST_LDFLAGS = $(SSL_LDFLAGS)
TEST_LDFLAGS = $(SSL_LDFLAGS) $(RDMA_LDFLAGS)
ifeq ($(USE_SSL),1)
TEST_LDFLAGS += -pthread
endif
Expand Down Expand Up @@ -232,6 +271,14 @@ $(SSL_PKGCONFNAME): $(SSL_PKGCONF_TEMPLATE)
-e 's|@PROJECT_VERSION@|$(LIBVALKEY_SONAME)|g' \
$< > $@

$(RDMA_PKGCONFNAME): $(RDMA_PKGCONF_TEMPLATE)
@echo "Generating $@ for pkgconfig..."
sed \
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|g' \
-e 's|@CMAKE_INSTALL_LIBDIR@|$(INSTALL_LIBRARY_PATH)|g' \
-e 's|@PROJECT_VERSION@|$(LIBVALKEY_SONAME)|g' \
$< > $@

install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) $(SSL_INSTALL)
mkdir -p $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH)
$(INSTALL) $(HEADERS) $(INSTALL_INCLUDE_PATH)
Expand All @@ -253,6 +300,16 @@ install-ssl: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME)
mkdir -p $(INSTALL_PKGCONF_PATH)
$(INSTALL) $(SSL_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)

install-rdma: $(RDMA_DYLIBNAME) $(RDMA_STLIBNAME) $(RDMA_PKGCONFNAME)
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
$(INSTALL) $(INCLUDE_DIR)/valkey_rdma.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) $(RDMA_DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_DYLIB_MINOR_NAME)
ln -sf $(RDMA_DYLIB_MINOR_NAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_ROOT_DYLIB_NAME)
ln -sf $(RDMA_DYLIB_MINOR_NAME) $(INSTALL_LIBRARY_PATH)/$(RDMA_DYLIB_MAJOR_NAME)
$(INSTALL) $(RDMA_STLIBNAME) $(INSTALL_LIBRARY_PATH)
mkdir -p $(INSTALL_PKGCONF_PATH)
$(INSTALL) $(RDMA_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)

32bit:
@echo ""
@echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"
Expand Down
10 changes: 2 additions & 8 deletions include/valkey/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,10 @@
#include "valkey.h"

void valkeyNetClose(valkeyContext *c);
ssize_t valkeyNetRead(valkeyContext *c, char *buf, size_t bufcap);
ssize_t valkeyNetWrite(valkeyContext *c);

int valkeyCheckSocketError(valkeyContext *c);
int valkeyContextSetTimeout(valkeyContext *c, const struct timeval tv);
int valkeyContextConnectTcp(valkeyContext *c, const char *addr, int port, const struct timeval *timeout);
int valkeyContextConnectBindTcp(valkeyContext *c, const char *addr, int port,
const struct timeval *timeout,
const char *source_addr);
int valkeyContextConnectUnix(valkeyContext *c, const char *path, const struct timeval *timeout);
int valkeyTcpSetTimeout(valkeyContext *c, const struct timeval tv);
int valkeyContextConnectTcp(valkeyContext *c, const valkeyOptions *options);
int valkeyKeepAlive(valkeyContext *c, int interval);
int valkeyCheckConnectDone(valkeyContext *c, int *completed);

Expand Down
7 changes: 6 additions & 1 deletion include/valkey/valkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ void valkeyFreeSdsCommand(sds cmd);
enum valkeyConnectionType {
VALKEY_CONN_TCP,
VALKEY_CONN_UNIX,
VALKEY_CONN_USERFD
VALKEY_CONN_USERFD,
VALKEY_CONN_RDMA, /* experimental, may be removed in any version */

VALKEY_CONN_MAX
};

struct valkeySsl;
Expand Down Expand Up @@ -239,6 +242,7 @@ typedef struct {
} while(0)

typedef struct valkeyContextFuncs {
int (*connect)(struct valkeyContext *, const valkeyOptions *);
void (*close)(struct valkeyContext *);
void (*free_privctx)(void *);
void (*async_read)(struct valkeyAsyncContext *);
Expand All @@ -250,6 +254,7 @@ typedef struct valkeyContextFuncs {
* recoverable error, they should return 0. */
ssize_t (*read)(struct valkeyContext *, char *, size_t);
ssize_t (*write)(struct valkeyContext *);
int (*set_timeout)(struct valkeyContext *, const struct timeval);
} valkeyContextFuncs;


Expand Down
60 changes: 60 additions & 0 deletions include/valkey/valkey_rdma.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

/*
* Copyright (c) 2021-2024 zhenwei pi <[email protected]>
*
* Valkey Over RDMA has been supported as experimental feature since Valkey-8.0.
* It's also supported as an experimental feature by libvalkey,
* It may be removed or changed in any version.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef VALKEY_RDMA_H
#define VALKEY_RDMA_H

#ifdef __cplusplus
extern "C" {
#endif

/**
* Helper macros to initialize options for RDMA.
* It's ok to reuse TCP options.
*/
#define VALKEY_OPTIONS_SET_RDMA(opts, ip_, port_) do { \
(opts)->type = VALKEY_CONN_RDMA; \
(opts)->endpoint.tcp.ip = ip_; \
(opts)->endpoint.tcp.port = port_; \
} while(0)


int valkeyInitiateRdma(void);

#ifdef __cplusplus
}
#endif

#endif /* VALKEY_RDMA_H */
59 changes: 59 additions & 0 deletions src/conn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024, zhenwei pi <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "valkey_private.h"

#include <assert.h>

static valkeyContextFuncs *valkeyContextFuncsArray[VALKEY_CONN_MAX];

int valkeyContextRegisterFuncs(valkeyContextFuncs *funcs, enum valkeyConnectionType type) {
assert(type < VALKEY_CONN_MAX);
assert(!valkeyContextFuncsArray[type]);

valkeyContextFuncsArray[type] = funcs;
return VALKEY_OK;
}

void valkeyContextSetFuncs(valkeyContext *c) {
static int initialized;

if (!initialized) {
initialized = 1;
valkeyContextRegisterTcpFuncs();
valkeyContextRegisterUnixFuncs();
valkeyContextRegisterUserfdFuncs();
}

assert(c->connection_type < VALKEY_CONN_MAX);
assert(!c->funcs);
c->funcs = valkeyContextFuncsArray[c->connection_type];
assert(c->funcs != NULL);
}
Loading
Loading