diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eca15771bdc8a9f261a509e131bf3b21bb91a21..cbe091aba1111b693fa4a9ca90e4a13ad809a1a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,8 @@ option(BUILD_PYTHON_DOCS "Uses sphinx to build the Python documentaion" OFF) option(BUILD_CONSUMER_TOOLS "Build consumer tools" OFF) option(BUILD_EXAMPLES "Build examples" OFF) +option(ENABLE_LIBFABRIC "Enables LibFabric support for RDMA transfers" OFF) + set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules/) set (ASAPO_CXX_COMMON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common/cpp/include) @@ -61,7 +63,16 @@ if ("${Python_EXECUTABLE}" STREQUAL "") endif() message (STATUS "Using Python: ${Python_EXECUTABLE}") - +IF(ENABLE_LIBFABRIC) + find_package(LibFabric) + if(NOT LIBFABRIC_LIBRARY) + message(FATAL_ERROR "Did not find libfabric") + endif() + message(STATUS "LibFabric support enabled") + message(STATUS "LIB_FABRIC: Path: ${LIBFABRIC_LIBRARY} Include: ${LIBFABRIC_INCLUDE_DIR}") + SET_PROPERTY(GLOBAL PROPERTY ASAPO_COMMON_FABRIC_LIBRARIES ${ASAPO_COMMON_IO_LIBRARIES} libfabric) + add_definitions(-DLIBFABRIC_ENABLED) +ENDIF() # format sources include(astyle) diff --git a/CMakeModules/FindLibFabric.cmake b/CMakeModules/FindLibFabric.cmake new file mode 100644 index 0000000000000000000000000000000000000000..24b54d5b1991820ae24ae3777d05c5ba5e98c41f --- /dev/null +++ b/CMakeModules/FindLibFabric.cmake @@ -0,0 +1,15 @@ +# FindLibFabric +# ------------- +# +# Tries to find LibFabric on the system +# +# Available variables +# LIBFABRIC_LIBRARY - Path to the library +# LIBFABRIC_INCLUDE_DIR - Path to the include dir + +cmake_minimum_required(VERSION 2.6) + +find_path(LIBFABRIC_INCLUDE_DIR fabric.h) +find_library(LIBFABRIC_LIBRARY fabric) + +mark_as_advanced(LIBFABRIC_INCLUDE_DIR LIBFABRIC_LIBRARY) diff --git a/common/cpp/CMakeLists.txt b/common/cpp/CMakeLists.txt index d7770ef6ae91190d5033aca819c860dfbf6d58d0..cfa9198b4acab97307960a1b03f3aae701f094a1 100644 --- a/common/cpp/CMakeLists.txt +++ b/common/cpp/CMakeLists.txt @@ -12,6 +12,8 @@ add_subdirectory(src/logger) add_subdirectory(src/request) +add_subdirectory(src/asapo_fabric) + if(BUILD_MONGODB_CLIENTLIB) add_subdirectory(src/database) endif() diff --git a/common/cpp/include/asapo_fabric/asapo_fabric.h b/common/cpp/include/asapo_fabric/asapo_fabric.h new file mode 100644 index 0000000000000000000000000000000000000000..5399c3a3b5d046c9c09ce74f9fc63cfb1399dbc6 --- /dev/null +++ b/common/cpp/include/asapo_fabric/asapo_fabric.h @@ -0,0 +1,76 @@ +#ifndef ASAPO_FABRIC_H +#define ASAPO_FABRIC_H + +#include <cstdint> +#include <string> +#include <memory> +#include <common/error.h> + +namespace asapo { namespace fabric { + typedef uint64_t FabricAddress; + typedef uint64_t FabricMessageId; + +#pragma pack(push, 1) + struct MemoryRegionDetails { + uint64_t addr; + uint64_t length; + uint64_t key; + }; +#pragma pack(pop) + + class FabricMemoryRegion { + public: + virtual ~FabricMemoryRegion() = default; + virtual MemoryRegionDetails* GetDetails() = 0; + }; + + class FabricContext { + public: + /// If this function is not called, the default timeout is 5000 ms + virtual void SetRequestTimeout(uint64_t msTimeout) = 0; + + virtual std::string GetAddress() const = 0; + + virtual std::unique_ptr<FabricMemoryRegion> ShareMemoryRegion(void* src, size_t size, Error* error) = 0; + + virtual void Send(FabricAddress dstAddress, FabricMessageId messageId, + const void* src, size_t size, Error* error) = 0; + + virtual void Recv(FabricAddress srcAddress, FabricMessageId messageId, + void* dst, size_t size, Error* error) = 0; + + virtual void RdmaWrite(FabricAddress dstAddress, + MemoryRegionDetails* details, const void* buffer, size_t size, + Error* error) = 0; + + // Since RdmaRead heavily impacts the performance we will not implement this + // virtual void RdmaRead(...) = 0; + + + }; + + class FabricClient : public FabricContext { + public: + virtual ~FabricClient() = default; + + virtual FabricAddress AddServerAddress(const std::string& serverAddress, Error* error) = 0; + }; + + class FabricServer : public FabricContext { + public: + virtual ~FabricServer() = default; + + virtual void RecvAny(FabricAddress* srcAddress, FabricMessageId* messageId, void* src, size_t size, Error* error) = 0; + }; + + class FabricFactory { + public: + virtual std::unique_ptr<FabricServer> CreateAndBindServer(Error* error) const = 0; + + virtual std::unique_ptr<FabricClient> CreateClient(Error* error) const = 0; + }; + + std::unique_ptr<FabricFactory> GenerateDefaultFabricFactory(); +}} + +#endif //ASAPO_FABRIC_H diff --git a/common/cpp/src/asapo_fabric/CMakeLists.txt b/common/cpp/src/asapo_fabric/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ad7e8b35488aa9aee1c5d083ac79b1418fac475c --- /dev/null +++ b/common/cpp/src/asapo_fabric/CMakeLists.txt @@ -0,0 +1,23 @@ +set(TARGET_NAME asapo-fabric) + +include_directories(include) + +set(SOURCE_FILES asapo_fabric.cpp) + +IF(ENABLE_LIBFABRIC) + set(SOURCE_FILES ${SOURCE_FILES} + fabric_factory_impl.cpp + ) +ELSE() + set(SOURCE_FILES ${SOURCE_FILES} + fabric_factory_not_supported.cpp + ) +ENDIF() + +################################ +# Library +################################ + +add_library(${TARGET_NAME} STATIC ${SOURCE_FILES}) + +target_include_directories(${TARGET_NAME} PUBLIC ${ASAPO_CXX_COMMON_INCLUDE_DIR}) diff --git a/common/cpp/src/asapo_fabric/asapo_fabric.cpp b/common/cpp/src/asapo_fabric/asapo_fabric.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96aa4fd5215db008e4ec0a9548b8db7bba9e31a9 --- /dev/null +++ b/common/cpp/src/asapo_fabric/asapo_fabric.cpp @@ -0,0 +1,17 @@ +#include <asapo_fabric/asapo_fabric.h> + +#ifdef LIBFABRIC_ENABLED +#include "fabric_factory_impl.h" +#else +#include "fabric_factory_not_supported.h" +#endif + +using namespace asapo::fabric; + +std::unique_ptr<FabricFactory> asapo::fabric::GenerateDefaultFabricFactory() { +#ifdef LIBFABRIC_ENABLED + return std::unique_ptr<FabricFactory>(new FabricFactoryImpl()); +#else + return std::unique_ptr<FabricFactory>(new FabricFactoryNotSupported()); +#endif +} diff --git a/common/cpp/src/asapo_fabric/fabric_factory_impl.cpp b/common/cpp/src/asapo_fabric/fabric_factory_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5c267ef8d16b863602f9e92dfadb1f6f86f7503 --- /dev/null +++ b/common/cpp/src/asapo_fabric/fabric_factory_impl.cpp @@ -0,0 +1,45 @@ +#include "fabric_factory_impl.h" +#include "fabric_internal_impl_common.h" +#include <rdma/fabric.h> + +using namespace asapo::fabric; + +std::string fi_version_string(uint32_t version) { + return std::to_string(FI_MAJOR(version)) + "." + std::to_string(FI_MINOR(version)); +} + +bool FabricFactoryImpl::HasValidVersion(Error* error) const { + auto current_version = fi_version(); + + if (FI_VERSION_LT(current_version, EXPECTED_FI_VERSION)) { + std::string found_version_str = fi_version_string(current_version); + std::string expected_version_str = fi_version_string(EXPECTED_FI_VERSION); + + std::string errorText = "LibFabric outdated."; + errorText += " (Found " + found_version_str + " but expected at least " + expected_version_str + ")"; + + *error = TextError(errorText); + return false; + } + + return true; +} + +std::unique_ptr<FabricClient> +FabricFactoryImpl::CreateClient(Error* error) const { + if (!HasValidVersion(error)) { + return nullptr; + } + + *error = TextError("This build of ASAPO does not support LibFabric."); + return nullptr; +} + +std::unique_ptr<FabricServer> FabricFactoryImpl::CreateAndBindServer(Error* error) const { + if (!HasValidVersion(error)) { + return nullptr; + } + + *error = TextError("This build of ASAPO does not support LibFabric."); + return nullptr; +} diff --git a/common/cpp/src/asapo_fabric/fabric_factory_impl.h b/common/cpp/src/asapo_fabric/fabric_factory_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..776d42a98cfc2fcc7c5466182f2841127ae55161 --- /dev/null +++ b/common/cpp/src/asapo_fabric/fabric_factory_impl.h @@ -0,0 +1,16 @@ +#include <asapo_fabric/asapo_fabric.h> + +#ifndef ASAPO_FABRIC_FACTORY_IMPL_H +#define ASAPO_FABRIC_FACTORY_IMPL_H + +namespace asapo { namespace fabric { + class FabricFactoryImpl : public FabricFactory { + bool HasValidVersion(Error* error) const; + + std::unique_ptr<FabricServer> CreateAndBindServer(Error* error) const override; + + std::unique_ptr<FabricClient> CreateClient(Error* error) const override; + }; +}} + +#endif //ASAPO_FABRIC_FACTORY_IMPL_H diff --git a/common/cpp/src/asapo_fabric/fabric_factory_not_supported.cpp b/common/cpp/src/asapo_fabric/fabric_factory_not_supported.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0508d997243270ca5edcf7e6a132e3d686ec109b --- /dev/null +++ b/common/cpp/src/asapo_fabric/fabric_factory_not_supported.cpp @@ -0,0 +1,14 @@ +#include "fabric_factory_not_supported.h" + +using namespace asapo::fabric; + +std::unique_ptr<FabricServer> asapo::fabric::FabricFactoryNotSupported::CreateAndBindServer(Error* error) const { + *error = TextError("This build of ASAPO does not support LibFabric."); + return nullptr; +} + +std::unique_ptr<FabricClient> asapo::fabric::FabricFactoryNotSupported::CreateClient(Error* error) const { + *error = TextError("This build of ASAPO does not support LibFabric."); + return nullptr; +} + diff --git a/common/cpp/src/asapo_fabric/fabric_factory_not_supported.h b/common/cpp/src/asapo_fabric/fabric_factory_not_supported.h new file mode 100644 index 0000000000000000000000000000000000000000..c701ac1a5e4f0b9d1f578385dd38056258c5b467 --- /dev/null +++ b/common/cpp/src/asapo_fabric/fabric_factory_not_supported.h @@ -0,0 +1,14 @@ +#ifndef ASAPO_FABRIC_FACTORY_NOT_SUPPORTED_H +#define ASAPO_FABRIC_FACTORY_NOT_SUPPORTED_H + +#include <asapo_fabric/asapo_fabric.h> + +namespace asapo { namespace fabric { + class FabricFactoryNotSupported : public FabricFactory { + std::unique_ptr<FabricServer> CreateAndBindServer(Error* error) const override; + + std::unique_ptr<FabricClient> CreateClient(Error* error) const override; + }; +}} + +#endif //ASAPO_FABRIC_FACTORY_NOT_SUPPORTED_H diff --git a/common/cpp/src/asapo_fabric/fabric_internal_impl_common.h b/common/cpp/src/asapo_fabric/fabric_internal_impl_common.h new file mode 100644 index 0000000000000000000000000000000000000000..73882fd0bb97987a3c38dec1173bfbd7afbffe36 --- /dev/null +++ b/common/cpp/src/asapo_fabric/fabric_internal_impl_common.h @@ -0,0 +1,23 @@ +#ifndef ASAPO_FABRIC_INTERNAL_IMPL_COMMON_H +#define ASAPO_FABRIC_INTERNAL_IMPL_COMMON_H + +/* + * This file contains common features used in ASAPO's integration of libfabric. + * Only include this file into *.cpp files, never in *.h files + */ + +#ifndef EXPECTED_FI_VERSION +#define EXPECTED_FI_VERSION FI_VERSION(1, 9) +#endif + +#pragma pack(push, 1) +struct HandshakePayload { + // Hostnames can be up to 256 Bytes long. We also need to store the port number. + char hostnameAndPort[512]; +}; + +#pragma pack(pop) + +#define TODO_UNKNOWN_ADDRESS (FI_ADDR_NOTAVAIL - 1) + +#endif //ASAPO_FABRIC_INTERNAL_IMPL_COMMON_H