From 69f57959d50cf08d063484551f15f6990582953d Mon Sep 17 00:00:00 2001 From: Timo Dritschler Date: Tue, 27 May 2014 15:30:08 +0200 Subject: Changed build system to CMake --- CMakeLists.txt | 68 ++++++++++ Makefile | 41 ------ kiro-client.c | 256 ------------------------------------- kiro-client.h | 90 ------------- kiro-rdma.h | 230 --------------------------------- kiro-server.c | 361 ---------------------------------------------------- kiro-server.h | 106 --------------- kiro-trb.c | 270 --------------------------------------- kiro-trb.h | 332 ----------------------------------------------- src/CMakeLists.txt | 2 + src/kiro-client.c | 256 +++++++++++++++++++++++++++++++++++++ src/kiro-client.h | 90 +++++++++++++ src/kiro-rdma.h | 230 +++++++++++++++++++++++++++++++++ src/kiro-server.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kiro-server.h | 106 +++++++++++++++ src/kiro-trb.c | 270 +++++++++++++++++++++++++++++++++++++++ src/kiro-trb.h | 332 +++++++++++++++++++++++++++++++++++++++++++++++ test-client.c | 97 -------------- test-server.c | 168 ------------------------ test.c | 51 -------- test/CMakeLists.txt | 8 ++ test/test-client.c | 97 ++++++++++++++ test/test-server.c | 168 ++++++++++++++++++++++++ test/test.c | 51 ++++++++ 24 files changed, 2039 insertions(+), 2002 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Makefile delete mode 100644 kiro-client.c delete mode 100644 kiro-client.h delete mode 100644 kiro-rdma.h delete mode 100644 kiro-server.c delete mode 100644 kiro-server.h delete mode 100644 kiro-trb.c delete mode 100644 kiro-trb.h create mode 100644 src/CMakeLists.txt create mode 100644 src/kiro-client.c create mode 100644 src/kiro-client.h create mode 100644 src/kiro-rdma.h create mode 100644 src/kiro-server.c create mode 100644 src/kiro-server.h create mode 100644 src/kiro-trb.c create mode 100644 src/kiro-trb.h delete mode 100644 test-client.c delete mode 100644 test-server.c delete mode 100644 test.c create mode 100644 test/CMakeLists.txt create mode 100644 test/test-client.c create mode 100644 test/test-server.c create mode 100644 test/test.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2f77f52 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +project(KIRO) + +cmake_minimum_required(VERSION 2.6) +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) + +set(TARNAME "kiro") +set(LIBKIRO_VERSION_MAJOR "0") +set(LIBKIRO_VERSION_MINOR "1") +set(LIBKIRO_VERSION_PATCH "0") +set(LIBKIRO_VERSION_RELEASE "1") +set(LIBKIRO_VERSION_STRING "${LIBKIRO_VERSION_MAJOR}.${LIBKIRO_VERSION_MINOR}.${LIBKIRO_VERSION_PATCH}") +set(VERSION "${LIBKIRO_VERSION_STRING}") +set(LIBKIRO_DESCRIPTION "Tango Device wrapper for an InfiniBand Server and Client") + +set(LIBKIRO_ABI_VERSION "${LIBKIRO_VERSION_MAJOR}.${LIBKIRO_VERSION_MINOR}") + +set(LIBKIRO_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +find_package(PkgConfig) +pkg_check_modules(GLIB2 glib-2.0>=2.24 REQUIRED) +pkg_check_modules(GOBJECT2 gobject-2.0>=2.24 REQUIRED) + +include_directories( + SYSTEM + ${GLIB2_INCLUDE_DIRS} + ${GOBJECT2_INCLUDE_DIRS} +) + +add_definitions(-Wall -Wextra -std=c99) + +# check for 64 bit +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(LIB_INSTALL_DIR "lib64") +else() + set(LIB_INSTALL_DIR "lib") +endif() + +set(HEADER_INSTALL_DIR include/LIBKIRO) + +add_subdirectory(src) + +add_subdirectory(test) + +set(CPACK_PACKAGE_DESCRIPTION ${LIBKIRO_DESCRIPTION}) +set(CPACK_PACKAGE_NAME ${TARNAME}) +set(CPACK_PACKAGE_CONTACT "Timo Dritschler ") +set(CPACK_PACKAGE_VENDOR "Karlsruhe Institute of Technology") +set(CPACK_PACKAGE_VERSION_MAJOR "${LIBKIRO_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${LIBKIRO_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${LIBKIRO_VERSION_PATCH}") +set(CPACK_PACKAGE_RELEASE "${LIBKIRO_VERSION_RELEASE}") + +set(CPACK_GENERATOR "TGZ;RPM;") +set(CPACK_SOURCE_GENERATOR "TGZ") +set(CPACK_SOURCE_IGNORE_FILES "tags" ".git") +set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) +set(CPACK_SOURCE_PACKAGE_FILE_NAME "LIBKIRO-${LIBKIRO_VERSION_STRING}" CACHE INTERNAL "tarball basename") +set(CPACK_PACKAGE_FILE_NAME + "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}") + +set(LIBKIRO_PKG_PREFIX ${CMAKE_INSTALL_PREFIX}) +set(LIBKIRO_PKG_EXEC_PREFIX "${LIBKIRO_PKG_PREFIX}/bin") +set(LIBKIRO_PKG_LIBDIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}") +set(LIBKIRO_PKG_INCLUDEDIR "${LIBKIRO_PKG_PREFIX}/include") + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/LIBKIRO.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +include(CPack) diff --git a/Makefile b/Makefile deleted file mode 100644 index 92f5508..0000000 --- a/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -CC=gcc -CFLAGS=-std=c99 -Wall -g -gdwarf-2 $(shell pkg-config --cflags gobject-2.0) -LDFLAGS=-lSDL -lm -lrdmacm -libverbs -lpthread $(shell pkg-config --libs gobject-2.0) - - -.PHONY : all -all: base - -base: kiro-trb.o kiro-client.o kiro-server.o - -kiro-trb.o: kiro-trb.c kiro-trb.h - $(CC) $(CFLAGS) $(LDFLAGS) -c kiro-trb.c -o kiro-trb.o - -kiro-client.o: kiro-client.c kiro-client.h - $(CC) $(CFLAGS) $(LDFLAGS) -c kiro-client.c -o kiro-client.o - -kiro-server.o: kiro-server.c kiro-server.h - $(CC) $(CFLAGS) $(LDFLAGS) -c kiro-server.c -o kiro-server.o - - -.PHONY : test -test: test-trb client server - -test-trb: kiro-trb.o test.c - $(CC) $(CFLAGS) $(LDFLAGS) test.c kiro-trb.o -o test-trb - -client: kiro-client.o kiro-trb.o test-client.c - $(CC) $(CFLAGS) $(LDFLAGS) test-client.c kiro-client.o kiro-trb.o -o client - -server: kiro-server.o kiro-trb.o test-server.c - $(CC) $(CFLAGS) $(LDFLAGS) test-server.c kiro-server.o kiro-trb.o -o server - - -.PHONY : clean -clean: - rm -f *.o test-trb client server - - -.PHONY : rebuild -rebuild: clean all - diff --git a/kiro-client.c b/kiro-client.c deleted file mode 100644 index 807d7d5..0000000 --- a/kiro-client.c +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-client - * @Short_description: KIRO RDMA Client / Consumer - * @Title: KiroClient - * - * KiroClient implements the client / active / consumer side of the the RDMA - * Communication Channel. It uses a KIRO-CLIENT to manage data read from the Server. - */ - -#include -#include -#include -#include -#include -#include -#include "kiro-client.h" -#include "kiro-rdma.h" -#include "kiro-trb.h" - -#include - - -/* - * Definition of 'private' structures and members and macro to access them - */ - -#define KIRO_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_CLIENT, KiroClientPrivate)) - -struct _KiroClientPrivate { - - /* Properties */ - // PLACEHOLDER // - - /* 'Real' private structures */ - /* (Not accessible by properties) */ - struct rdma_event_channel *ec; // Main Event Channel - struct rdma_cm_id *conn; // Connection to the Server - -}; - - -G_DEFINE_TYPE_WITH_PRIVATE (KiroClient, kiro_client, G_TYPE_OBJECT); - - -static void kiro_client_init (KiroClient *self) -{ - KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); - memset(priv, 0, sizeof(&priv)); -} - -static void -kiro_client_finalize (GObject *object) -{ - //KiroClient *self = KIRO_CLIENT(object); - //KiroClientPrivate * priv = KIRO_CLIENT_GET_PRIVATE(self); - //PASS -} - -static void -kiro_client_class_init (KiroClientClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = kiro_client_finalize; -} - - - -int kiro_client_connect (KiroClient *self, char *address, char* port) -{ - KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); - - if(priv->conn) - { - printf("Already connected to server.\n"); - return -1; - } - - struct rdma_addrinfo hints, *res_addrinfo; - memset(&hints, 0, sizeof(hints)); - hints.ai_port_space = RDMA_PS_IB; - if(rdma_getaddrinfo(address, port, &hints, &res_addrinfo)) - { - printf("Failed to contruct address information for %s:%s\n",address, port); - return -1; - } - printf("Address information created.\n"); - - struct ibv_qp_init_attr qp_attr; - memset(&qp_attr, 0, sizeof(qp_attr)); - qp_attr.cap.max_send_wr = 10; - qp_attr.cap.max_recv_wr = 10; - qp_attr.cap.max_send_sge = 1; - qp_attr.cap.max_recv_sge = 1; - qp_attr.qp_context = priv->conn; - qp_attr.sq_sig_all = 1; - - if(rdma_create_ep(&(priv->conn), res_addrinfo, NULL, &qp_attr)) - { - printf("Endpoint creation failed with error: %i\n", errno); - return -1; - } - printf("Route to server resolved.\n"); - - struct kiro_connection_context *ctx = (struct kiro_connection_context *)calloc(1,sizeof(struct kiro_connection_context)); - if(!ctx) - { - printf("Failed to create connection context.\n"); - rdma_destroy_ep(priv->conn); - return -1; - } - - ctx->cf_mr_send = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - ctx->cf_mr_recv = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - if(!ctx->cf_mr_recv || !ctx->cf_mr_send) - { - printf("Failed to allocate Control Flow Memory Container.\n"); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - - ctx->cf_mr_recv = kiro_create_rdma_memory(priv->conn->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); - ctx->cf_mr_send = kiro_create_rdma_memory(priv->conn->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); - if(!ctx->cf_mr_recv || !ctx->cf_mr_send) - { - printf("Failed to register control message memory.\n"); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - ctx->cf_mr_recv->size = ctx->cf_mr_send->size = sizeof(struct kiro_ctrl_msg); - priv->conn->context = ctx; - - if(rdma_post_recv(priv->conn, priv->conn, ctx->cf_mr_recv->mem, ctx->cf_mr_recv->size, ctx->cf_mr_recv->mr)) - { - printf("Posting preemtive receive for connection failed with error: %i\n", errno); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - - if(rdma_connect(priv->conn, NULL)) - { - printf("Failed to establish connection to the server.\n"); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - printf("Connected to server.\n"); - - - struct ibv_wc wc; - if(rdma_get_recv_comp(priv->conn, &wc) < 0) - { - printf("Failure waiting for POST from server.\n"); - rdma_disconnect(priv->conn); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - printf("Got Message from Server.\n"); - ctx->peer_mr = (((struct kiro_ctrl_msg *)(ctx->cf_mr_recv->mem))->peer_mri); - printf("Expected Memory Size is: %u\n",ctx->peer_mr.length); - - ctx->rdma_mr = kiro_create_rdma_memory(priv->conn->pd, ctx->peer_mr.length, IBV_ACCESS_LOCAL_WRITE); - if(!ctx->rdma_mr) - { - printf("Failed to allocate memory for receive buffer.\n"); - rdma_disconnect(priv->conn); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - printf("Connection setup completed successfully!\n"); - - return 0; -} - - - -int kiro_client_sync (KiroClient *self) -{ - KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); - struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; - - if(rdma_post_read(priv->conn, priv->conn, ctx->rdma_mr->mem, ctx->peer_mr.length, ctx->rdma_mr->mr, 0, ctx->peer_mr.addr, ctx->peer_mr.rkey)) - { - printf("Failed to read from server.\n"); - rdma_disconnect(priv->conn); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - - struct ibv_wc wc; - if(rdma_get_send_comp(priv->conn, &wc) < 0) - { - printf("Failure reading from server.\n"); - rdma_disconnect(priv->conn); - kiro_destroy_connection_context(&ctx); - rdma_destroy_ep(priv->conn); - return -1; - } - return 0; -} - - -void* kiro_client_get_memory (KiroClient *self) -{ - KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); - if(!priv->conn) - return NULL; - - struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; - if(!ctx->rdma_mr) - return NULL; - - return ctx->rdma_mr->mem; -} - - -size_t kiro_client_get_memory_size (KiroClient *self) -{ - KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); - if(!priv->conn) - return 0; - - struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; - if(!ctx->rdma_mr) - return 0; - - return ctx->rdma_mr->size; -} - - - - - diff --git a/kiro-client.h b/kiro-client.h deleted file mode 100644 index e3e60de..0000000 --- a/kiro-client.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-client - * @Short_description: KIRO RDMA Client / Consumer - * @Title: KiroClient - * - * KiroClient implements the client / active / consumer side of the the RDMA - * Communication Channel. It uses a KIRO-CLIENT to manage data read from the Server. - */ - -#ifndef __KIRO_CLIENT_H -#define __KIRO_CLIENT_H - -#include -#include - -G_BEGIN_DECLS - -#define KIRO_TYPE_CLIENT (kiro_client_get_type()) -#define KIRO_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_CLIENT, KiroClient)) -#define KIRO_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_CLIENT)) -#define KIRO_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_CLIENT, KiroClientClass)) -#define KIRO_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_CLIENT)) -#define KIRO_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_CLIENT, KiroClientClass)) - - -typedef struct _KiroClient KiroClient; -typedef struct _KiroClientClass KiroClientClass; -typedef struct _KiroClientPrivate KiroClientPrivate; - - -struct _KiroClient { - - GObject parent; - - /*< private >*/ - KiroClientPrivate *priv; -}; - - -/** - * IbvConnectorInterface: - * - * Base interface for IbvConnectors. - */ - -struct _KiroClientClass { - - GObjectClass parent_class; - -}; - - - -/* GObject and GType functions */ -GType kiro_client_get_type (void); - -GObject kiro_client_new (void); - -/* client functions */ - - -int kiro_client_connect (KiroClient* client, char* dest_addr, char* dest_port); - -int kiro_client_sync (KiroClient* client); - -void* kiro_client_get_memory (KiroClient* client); - -size_t kior_client_get_memory_size (KiroClient* client); - -G_END_DECLS - -#endif //__KIRO_CLIENT_H \ No newline at end of file diff --git a/kiro-rdma.h b/kiro-rdma.h deleted file mode 100644 index fa16fd1..0000000 --- a/kiro-rdma.h +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -#include -#include -#include -#ifndef __KIRO_RDMA_H__ -#define __KIRO_RDMA_H__ - - -#include - - -struct kiro_connection_context { - - // Information and necessary structurs - uint32_t identifier; // Unique Identifier for this connection (Application Specific) - struct kiro_rdma_mem *cf_mr_recv; // Control-Flow Memory Region Receive - struct kiro_rdma_mem *cf_mr_send; // Control-Flow Memory Region Send - struct kiro_rdma_mem *rdma_mr; // Memory Region for RDMA Operations - - struct ibv_mr peer_mr; // RDMA Memory Region Information of the peer - - enum { - KIRO_IDLE, - KIRO_MRI_REQUESTED, // Memory Region Information Requested - KIRO_RDMA_ESTABLISHED, // MRI Exchange complete. RDMA is ready - KIRO_RDMA_ACTIVE // RDMA Operation is being performed - } rdma_state; - -}; - - -struct kiro_connection { - - uint32_t identifier; - struct rdma_cm_id *id; - struct kiro_connection *next; - -}; - - -struct kiro_ctrl_msg { - - enum { - KIRO_REQ_RDMA, // Requesting RDMA Access to/from the peer - KIRO_ACK_RDMA, // acknowledge RDMA Request and provide Memory Region Information - KIRO_REJ_RDMA // RDMA Request rejected :( (peer_mri will be invalid) - } msg_type; - - struct ibv_mr peer_mri; - -}; - - -struct kiro_rdma_mem { - - void *mem; // Pointer to the beginning of the memory block - struct ibv_mr *mr; // Memory Region associated with the memory - size_t size; // Size in Bytes of the memory block - -}; - - -static int kiro_attach_qp (struct rdma_cm_id *id) -{ - if(!id) - return -1; - - id->pd = ibv_alloc_pd(id->verbs); - id->send_cq_channel = ibv_create_comp_channel(id->verbs); - id->recv_cq_channel = id->send_cq_channel; //we use one shared completion channel - id->send_cq = ibv_create_cq(id->verbs, 1, id, id->send_cq_channel, 0); - id->recv_cq = id->send_cq; //we use one shared completion queue - - struct ibv_qp_init_attr qp_attr; - memset(&qp_attr, 0, sizeof(struct ibv_qp_init_attr)); - qp_attr.qp_context = (uintptr_t)id; - qp_attr.send_cq = id->send_cq; - qp_attr.recv_cq = id->recv_cq; - qp_attr.qp_type = IBV_QPT_RC; - qp_attr.cap.max_send_wr = 1; - qp_attr.cap.max_recv_wr = 1; - qp_attr.cap.max_send_sge = 1; - qp_attr.cap.max_recv_sge = 1; - - return rdma_create_qp(id, id->pd, &qp_attr); -} - - -static int kiro_register_rdma_memory (struct ibv_pd *pd, struct ibv_mr **mr, void *mem, size_t mem_size, int access) -{ - - if(mem_size == 0) - { - printf("Cant allocate memory of size '0'.\n"); - return -1; - } - - void *mem_handle = mem; - - if(!mem_handle) - mem_handle = malloc(mem_size); - - if(!mem_handle) - { - printf("Failed to allocate memory [Register Memory]."); - return -1; - } - - *mr = ibv_reg_mr(pd, mem_handle, mem_size, access); - if(!(*mr)) - { - // Memory Registration failed - printf("Failed to register memory region!\n"); - free(mem_handle); - return -1; - } - - return 0; -} - - -static struct kiro_rdma_mem* kiro_create_rdma_memory (struct ibv_pd *pd, size_t mem_size, int access) -{ - if(mem_size == 0) - { - printf("Cant allocate memory of size '0'.\n"); - return NULL; - } - - struct kiro_rdma_mem *krm = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - if(!krm) - { - printf("Failed to create new KIRO RDMA Memory.\n"); - return NULL; - } - - if(kiro_register_rdma_memory(pd, &(krm->mr), krm->mem, mem_size, access)) - { - free(krm); - return NULL; - } - - if(!krm->mem) - krm->mem = krm->mr->addr; - - - return krm; - -} - - -static void kiro_destroy_rdma_memory (struct kiro_rdma_mem *krm) -{ - if(!krm) - return; - - if(krm->mr) - ibv_dereg_mr(krm->mr); - - if(krm->mem) - free(krm->mem); - - free(krm); - krm = NULL; -} - - -static void kiro_destroy_connection_context (struct kiro_connection_context **ctx) -{ - if(!ctx) - return; - - if(!(*ctx)) - return; - - if((*ctx)->cf_mr_recv) - kiro_destroy_rdma_memory((*ctx)->cf_mr_recv); - if((*ctx)->cf_mr_send) - kiro_destroy_rdma_memory((*ctx)->cf_mr_send); - - //The RDMA-Memory Region normally contains allocated memory from the USER that has - //just been 'registered' for RDMA. DON'T free it! Just deregister it. The user is - //responsible for freeing this memory. - if((*ctx)->rdma_mr) - { - if((*ctx)->rdma_mr->mr) - ibv_dereg_mr((*ctx)->rdma_mr->mr); - - free((*ctx)->rdma_mr); - (*ctx)->rdma_mr = NULL; - } - - free(*ctx); - *ctx = NULL; -} - - -static void kiro_destroy_connection (struct rdma_cm_id **conn) -{ - if(!(*conn)) - return; - - rdma_disconnect(*conn); - struct kiro_connection_context *ctx = (struct kiro_connection_context *)((*conn)->context); - if(ctx) - kiro_destroy_connection_context(&ctx); - - rdma_destroy_ep(*conn); - *conn = NULL; -} - - -#endif //__KIRO_RDMA_H__ \ No newline at end of file diff --git a/kiro-server.c b/kiro-server.c deleted file mode 100644 index 52304c8..0000000 --- a/kiro-server.c +++ /dev/null @@ -1,361 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-server - * @Short_description: KIRO RDMA Server / Consumer - * @Title: KiroServer - * - * KiroServer implements the server / passive / provider side of the the RDMA - * Communication Channel. It uses a KIRO-TRB to manage its data. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "kiro-server.h" -#include "kiro-rdma.h" -#include "kiro-trb.h" - - -/* - * Definition of 'private' structures and members and macro to access them - */ - -#define KIRO_SERVER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_SERVER, KiroServerPrivate)) - -struct _KiroServerPrivate { - - /* Properties */ - // PLACEHOLDER // - - /* 'Real' private structures */ - /* (Not accessible by properties) */ - struct rdma_event_channel *ec; // Main Event Channel - struct rdma_cm_id *base; // Base-Listening-Connection - struct kiro_connection *client; // Connection to the client - pthread_t event_listener; // Pointer to the completion-listener thread of this connection - pthread_mutex_t mtx; // Mutex to signal the listener-thread termination - void *mem; // Pointer to the server buffer - size_t mem_size; // Server Buffer Size in bytes - -}; - - -G_DEFINE_TYPE_WITH_PRIVATE (KiroServer, kiro_server, G_TYPE_OBJECT); - - -static void kiro_server_init (KiroServer *self) -{ - KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE(self); - memset(priv, 0, sizeof(&priv)); -} - - -static void -kiro_server_finalize (GObject *object) -{ - //PASS -} - - -static void -kiro_server_class_init (KiroServerClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = kiro_server_finalize; -} - - -static int connect_client (struct rdma_cm_id *client) -{ - if(!client) - return -1; - - if( -1 == kiro_attach_qp(client)) - { - printf("Could not create a QP for the new connection.\n"); - rdma_destroy_id(client); - return -1; - } - - struct kiro_connection_context *ctx = (struct kiro_connection_context *)calloc(1,sizeof(struct kiro_connection_context)); - if(!ctx) - { - printf("Failed to create connection context.\n"); - rdma_destroy_id(client); - return -1; - } - - ctx->cf_mr_send = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - ctx->cf_mr_recv = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - if(!ctx->cf_mr_recv || !ctx->cf_mr_send) - { - printf("Failed to allocate Control Flow Memory Container.\n"); - goto error; - } - - ctx->cf_mr_recv = kiro_create_rdma_memory(client->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); - ctx->cf_mr_send = kiro_create_rdma_memory(client->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); - if(!ctx->cf_mr_recv || !ctx->cf_mr_send) - { - printf("Failed to register control message memory.\n"); - goto error; - } - ctx->cf_mr_recv->size = ctx->cf_mr_send->size = sizeof(struct kiro_ctrl_msg); - client->context = ctx; - - if(rdma_post_recv(client, client, ctx->cf_mr_recv->mem, ctx->cf_mr_recv->size, ctx->cf_mr_recv->mr)) - { - printf("Posting preemtive receive for connection failed.\n"); - goto error; - } - - if(rdma_accept(client, NULL)) - { - printf("Failed to establish connection to the client with error: %i.\n", errno); - goto error; - } - printf("Client Connected.\n"); - return 0; - - -error: - rdma_reject(client, NULL, 0); - kiro_destroy_connection_context(&ctx); - rdma_destroy_id(client); - return -1; -} - - -static int welcome_client (struct rdma_cm_id *client, void *mem, size_t mem_size) -{ - struct kiro_connection_context *ctx = (struct kiro_connection_context *)(client->context); - ctx->rdma_mr = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); - if(!ctx->rdma_mr) - { - printf("Failed to allocate RDMA Memory Container.\n"); - return -1; - } - - ctx->rdma_mr->mem = mem; - ctx->rdma_mr->size = mem_size; - ctx->rdma_mr->mr = rdma_reg_read(client, ctx->rdma_mr->mem, ctx->rdma_mr->size); - if(!ctx->rdma_mr->mr) - { - printf("Failed to register RDMA Memory Region.\n"); - kiro_destroy_rdma_memory(ctx->rdma_mr); - return -1; - } - - struct kiro_ctrl_msg *msg = (struct kiro_ctrl_msg *)(ctx->cf_mr_send->mem); - msg->msg_type = KIRO_ACK_RDMA; - msg->peer_mri = *(ctx->rdma_mr->mr); - - if(rdma_post_send(client, client, ctx->cf_mr_send->mem, ctx->cf_mr_send->size, ctx->cf_mr_send->mr, IBV_SEND_SIGNALED)) - { - printf("Failure while trying to post SEND.\n"); - kiro_destroy_rdma_memory(ctx->rdma_mr); - return -1; - } - - struct ibv_wc wc; - - if(rdma_get_send_comp(client, &wc) < 0) - { - printf("Failed to post RDMA MRI to client.\n"); - kiro_destroy_rdma_memory(ctx->rdma_mr); - return -1; - } - printf("RDMA MRI sent to client.\n"); - - return 0; -} - - -void * event_loop (void *self) -{ - KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE((KiroServer *)self); - struct rdma_cm_event *active_event; - - int stop = 0; - - while(0 == stop) { - if(0 <= rdma_get_cm_event(priv->ec, &active_event)) - { - - struct rdma_cm_event *ev = malloc(sizeof(*active_event)); - if(!ev) - { - printf("Unable to allocate memory for Event handling!\n"); - rdma_ack_cm_event(active_event); - continue; - } - memcpy(ev, active_event, sizeof(*active_event)); - rdma_ack_cm_event(active_event); - - if (ev->event == RDMA_CM_EVENT_CONNECT_REQUEST) - { - - /* - priv->client = (struct kiro_connection *)calloc(1, sizeof(struct kiro_connection)); - if(!(priv->client)) - { - printf("Failed to create container for client connection.\n"); - free(ev); - continue; - } - priv->client->identifier = 0; //First Client - priv->client->id = ev->id; - */ - - if(0 == connect_client(ev->id)) - { - // Connection set-up successfully! (Server) - // Post a welcoming "Recieve" for handshaking - welcome_client(ev->id, priv->mem, priv->mem_size); - } - } - else if(ev->event == RDMA_CM_EVENT_DISCONNECTED) - { - printf("Got disconnect request.\n"); - //pthread_mutex_unlock(&(priv->mtx)); - kiro_destroy_connection(&(ev->id)); - printf("Connection closed successfully\n"); - } - free(ev); - } - - // Mutex will be freed as a signal to stop request - if(0 == pthread_mutex_trylock(&(priv->mtx))) - stop = 1; - } - - printf("Closing Event Listener Thread\n"); - return NULL; -} - - - - -int kiro_server_start (KiroServer *self, char *address, char *port, void* mem, size_t mem_size) -{ - KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE(self); - - if(priv->base) - { - printf("Server already started.\n"); - return -1; - } - - if(!mem || mem_size == 0) - { - printf("Invalid memory given to provide.\n"); - return -1; - } - - struct rdma_addrinfo hints, *res_addrinfo; - memset(&hints, 0, sizeof(hints)); - hints.ai_port_space = RDMA_PS_IB; - hints.ai_flags = RAI_PASSIVE; - if(rdma_getaddrinfo(address, port, &hints, &res_addrinfo)) - { - printf("Failed to create address information."); - return -1; - } - - struct ibv_qp_init_attr qp_attr; - memset(&qp_attr, 0, sizeof(qp_attr)); - qp_attr.cap.max_send_wr = 10; - qp_attr.cap.max_recv_wr = 10; - qp_attr.cap.max_send_sge = 1; - qp_attr.cap.max_recv_sge = 1; - qp_attr.qp_context = priv->base; - qp_attr.sq_sig_all = 1; - - if(rdma_create_ep(&(priv->base), res_addrinfo, NULL, &qp_attr)) - { - printf("Endpoint creation failed.\n"); - return -1; - } - printf("Endpoint created.\n"); - - char *addr_local = NULL; - struct sockaddr* src_addr = rdma_get_local_addr(priv->base); - if(!src_addr) - { - addr_local = "NONE"; - } - else - { - addr_local = inet_ntoa(((struct sockaddr_in *)src_addr)->sin_addr); - /* - if(src_addr->sa_family == AF_INET) - addr_local = &(((struct sockaddr_in*)src_addr)->sin_addr); - else - addr_local = &(((struct sockaddr_in6*)src_addr)->sin6_addr); - */ - } - - printf("Bound to address %s:%s\n",addr_local, port); - - if(rdma_listen(priv->base, 0)) - { - printf("Failed to put server into listening state.\n"); - rdma_destroy_ep(priv->base); - return -1; - } - - priv->mem = mem; - priv->mem_size = mem_size; - - priv->ec = rdma_create_event_channel(); - int oldflags = fcntl (priv->ec->fd, F_GETFL, 0); - /* Only change the FD Mode if we were able to get its flags */ - if (oldflags >= 0) { - oldflags |= O_NONBLOCK; - /* Store modified flag word in the descriptor. */ - fcntl (priv->ec->fd, F_SETFL, oldflags); - } - if(rdma_migrate_id(priv->base, priv->ec)) - { - printf("Was unable to migrate connection to new Event Channel.\n"); - rdma_destroy_ep(priv->base); - return -1; - } - - pthread_mutex_init(&(priv->mtx), NULL); - pthread_mutex_lock(&(priv->mtx)); - pthread_create(&(priv->event_listener), NULL, event_loop, self); - - printf("Enpoint listening.\n"); - - sleep(1); - return 0; -} - - - - - - - diff --git a/kiro-server.h b/kiro-server.h deleted file mode 100644 index cb9b57c..0000000 --- a/kiro-server.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-server - * @Short_description: KIRO RDMA Server / Consumer - * @Title: KiroServer - * - * KiroServer implements the server / passive / provider side of the the RDMA - * Communication Channel. It uses a KIRO-TRB to manage its data. - */ - -#ifndef __KIRO_SERVER_H -#define __KIRO_SERVER_H - -#include -#include - -G_BEGIN_DECLS - -#define KIRO_TYPE_SERVER (kiro_server_get_type()) -#define KIRO_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_SERVER, KiroServer)) -#define KIRO_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_SERVER)) -#define KIRO_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_SERVER, KiroServerClass)) -#define KIRO_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_SERVER)) -#define KIRO_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_SERVER, KiroServerClass)) - - -typedef struct _KiroServer KiroServer; -typedef struct _KiroServerClass KiroServerClass; -typedef struct _KiroServerPrivate KiroServerPrivate; - - -struct _KiroServer { - - GObject parent; - - /*< private >*/ - KiroServerPrivate *priv; -}; - - -/** - * IbvConnectorInterface: - * - * Base interface for IbvConnectors. - */ - -struct _KiroServerClass { - - GObjectClass parent_class; - -}; - - - -/* GObject and GType functions */ -GType kiro_server_get_type (void); - -GObject kiro_server_new (void); - -/* server functions */ - -/** - * kiro_server_start - Starts the server, providing the given memory - * @server: KIRO SERVER to perform the operation on - * @bind_addr: Local address to bind the server to - * @bind_port: Local port to listen for connections - * @mem: Pointer to the memory that is to be provided - * @mem_size: Size in bytes of the given memory - * Description: - * Starts the server to provide the given memory to any connecting - * client. - * Notes: - * If the bind_addr is NULL, the server will bind to the first device - * it can find on the machine and listen across all IPs. Otherwise it - * will try to bind to the device associated with the given address. - * Address is given as a string of either a hostname or a dot-seperated - * IPv4 address or a colon-seperated IPv6 hex-address. - * If bind_port is NULL the server will choose a free port randomly - * and return the chosen port as return value. - * If server creation fails, -1 is returned instead. - * See also: - * kiro_trb_reshape, kiro_trb_adopt, - * kiro_trb_clone - */ -int kiro_server_start (KiroServer* server, char* bind_addr, char* bind_port, void* mem, size_t mem_size); - -G_END_DECLS - -#endif //__KIRO_SERVER_H \ No newline at end of file diff --git a/kiro-trb.c b/kiro-trb.c deleted file mode 100644 index e81a4f7..0000000 --- a/kiro-trb.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-trb - * @Short_description: KIRO 'Transmittable Ring Buffer' - * @Title: KiroTrb - * - * KiroTrb implements a 'Transmittable Ring Buffer' that holds all necessary information - * about its content inside itself, so its data can be exchanged between different - * instances of the KiroTrb Class and/or sent over a network. - */ - -#include - -#include -#include -#include -#include "kiro-trb.h" - - -/* - * Definition of 'private' structures and members and macro to access them - */ - -#define KIRO_TRB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_TRB, KiroTrbPrivate)) - -struct _KiroTrbPrivate { - - /* Properties */ - // PLACEHOLDER // - - /* 'Real' private structures */ - /* (Not accessible by properties) */ - int initialized; // 1 if Buffer is Valid, 0 otherwise - void *mem; // Access to the actual buffer in Memory - void *frame_top; // First byte of the buffer storage - void *current; // Pointer to the current fill state - uint64_t element_size; - uint64_t max_elements; - uint64_t iteration; // How many times the buffer has wraped around - - /* easy access */ - uint64_t buff_size; -}; - - -G_DEFINE_TYPE_WITH_PRIVATE (KiroTrb, kiro_trb, G_TYPE_OBJECT); - - -static -void kiro_trb_init (KiroTrb *self) -{ - KiroTrbPrivate *priv = KIRO_TRB_GET_PRIVATE(self); - priv->initialized = 0; -} - -static void -kiro_trb_finalize (GObject *object) -{ - KiroTrb *self = KIRO_TRB(object); - KiroTrbPrivate *priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->mem) - free(priv->mem); -} - -static void -kiro_trb_class_init (KiroTrbClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = kiro_trb_finalize; -} - - -/* Privat functions */ - -void write_header (KiroTrbPrivate* priv) -{ - if(!priv) - return; - struct KiroTrbInfo* tmp_info = (struct KiroTrbInfo*)priv->mem; - tmp_info->buffer_size_bytes = priv->buff_size; - tmp_info->element_size = priv->element_size; - tmp_info->offset = (priv->iteration * priv->max_elements) + ((priv->current - priv->frame_top) / priv->element_size); - memcpy(priv->mem, tmp_info, sizeof(struct KiroTrbInfo)); -} - - - -/* TRB functions */ - -uint64_t kiro_trb_get_element_size (KiroTrb* self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return 0; - return priv->element_size; -} - - -uint64_t kiro_trb_get_max_elements (KiroTrb* self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return 0; - return priv->max_elements; -} - - -uint64_t kiro_trb_get_raw_size (KiroTrb* self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return 0; - return priv->buff_size; -} - - -void* kiro_trb_get_raw_buffer (KiroTrb* self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return NULL; - write_header(priv); - return priv->mem; -} - - - -void* kiro_trb_get_element (KiroTrb* self, uint64_t element) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return NULL; - - uint64_t relative = 0; - if(priv->iteration == 0) - relative = element * priv->element_size; - else - relative = ((priv->current - priv->frame_top) + (priv->element_size * element)) % (priv->buff_size - sizeof(struct KiroTrbInfo)); - - return priv->frame_top + relative; -} - - -void kiro_trb_flush (KiroTrb *self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - priv->iteration = 0; - priv->current = priv->frame_top; - write_header(priv); -} - - -int kiro_trb_is_setup (KiroTrb *self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - return priv->initialized; -} - - -int kiro_trb_reshape (KiroTrb *self, uint64_t element_size, uint64_t element_count) -{ - size_t new_size = (element_size * element_count) + sizeof(struct KiroTrbInfo); - void* newmem = malloc(new_size); - if(!newmem) - return -1; - ((struct KiroTrbInfo *)newmem)->buffer_size_bytes = new_size; - ((struct KiroTrbInfo *)newmem)->element_size = element_size; - ((struct KiroTrbInfo *)newmem)->offset = 0; - kiro_trb_adopt(self, newmem); - return 0; -} - - -int kiro_trb_push (KiroTrb *self, void *element_in) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return -1; - if((priv->current + priv->element_size) > (priv->mem + priv->buff_size)) - return -1; - memcpy(priv->current, element_in, priv->element_size); - priv->current += priv->element_size; - if(priv->current >= priv->frame_top + (priv->element_size * priv->max_elements)) - { - priv->current = priv->frame_top; - priv->iteration++; - } - write_header(priv); - return 0; -} - - -void* kiro_trb_dma_push (KiroTrb *self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return NULL; - if((priv->current + priv->element_size) > (priv->mem + priv->buff_size)) - return NULL; - void *mem_out = priv->current; - priv->current += priv->element_size; - if(priv->current >= priv->frame_top + (priv->element_size * priv->max_elements)) - { - priv->current = priv->frame_top; - priv->iteration++; - } - write_header(priv); - return mem_out; -} - - -void kiro_trb_refresh (KiroTrb *self) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->initialized != 1) - return; - struct KiroTrbInfo *tmp = (struct KiroTrbInfo *)priv->mem; - priv->buff_size = tmp->buffer_size_bytes; - priv->element_size = tmp->element_size; - priv->max_elements = (tmp->buffer_size_bytes - sizeof(struct KiroTrbInfo)) / tmp->element_size; - priv->iteration = tmp->offset / priv->max_elements; - priv->frame_top = priv->mem + sizeof(struct KiroTrbInfo); - priv->current = priv->frame_top + ((tmp->offset % priv->max_elements) * priv->element_size); - priv->initialized = 1; -} - - -void kiro_trb_adopt (KiroTrb *self, void *buff_in) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - if(priv->mem) - free(priv->mem); - priv->mem = buff_in; - priv->initialized = 1; - kiro_trb_refresh(self); -} - - -int kiro_trb_clone (KiroTrb *self, void *buff_in) -{ - KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); - struct KiroTrbInfo *header = (struct KiroTrbInfo *)buff_in; - void *newmem = malloc(header->buffer_size_bytes); - if(!newmem) - return -1; - memcpy(newmem, buff_in, header->buffer_size_bytes); - if(priv->mem) - free(priv->mem); - priv->mem = newmem; - priv->initialized = 1; - kiro_trb_refresh(self); - return 0; -} diff --git a/kiro-trb.h b/kiro-trb.h deleted file mode 100644 index 5c2b462..0000000 --- a/kiro-trb.h +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (C) 2014 Timo Dritschler - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA -*/ - -/** - * SECTION: kiro-trb - * @Short_description: KIRO 'Transmittable Ring Buffer' - * @Title: KiroTrb - * - * KiroTrb implements a 'Transmittable Ring Buffer' that holds all necessary information - * about its content inside itself, so its data can be exchanged between different - * instances of the KiroTrb Class and/or sent over a network. - */ - -#ifndef __KIRO_TRB_H -#define __KIRO_TBR_H - -#include -#include - -G_BEGIN_DECLS - -#define KIRO_TYPE_TRB (kiro_trb_get_type()) -#define KIRO_TRB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_TRB, KiroTrb)) -#define KIRO_IS_TRB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_TRB)) -#define KIRO_TRB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_TRB, KiroTrbClass)) -#define KIRO_IS_TRB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_TRB)) -#define KIRO_TRB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_TRB, KiroTrbClass)) - - -typedef struct _KiroTrb KiroTrb; -typedef struct _KiroTrbClass KiroTrbClass; -typedef struct _KiroTrbPrivate KiroTrbPrivate; - - -struct _KiroTrb { - - GObject parent; - -}; - - -/** - * IbvConnectorInterface: - * - * Base interface for IbvConnectors. - */ - -struct _KiroTrbClass { - - GObjectClass parent_class; - -}; - - -struct KiroTrbInfo { - - /* internal information about the buffer */ - uint64_t buffer_size_bytes; // Size in bytes INCLUDING this header - uint64_t element_size; // Size in bytes of one single element - uint64_t offset; // Current Offset to access the 'oldest' element (in element count!) - -} __attribute__((packed)); - - -/* GObject and GType functions */ -GType kiro_trb_get_type (void); - -GObject kiro_trb_new (void); - - -/* trb functions */ - -/** - * kiro_trb_get_element_size - Returns the element size in bytes - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns the size of the individual elements in the buffer - * See also: - * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone - */ -uint64_t kiro_trb_get_element_size (KiroTrb* trb); - -/** - * kiro_trb_get_max_elements - Returns the capacity of the buffer - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns the mximal number of elements that can be stored in - * the buffer - * See also: - * kiro_trb_get_element_size, kiro_trb_reshape, kiro_trb_adopt, - * kiro_trb_clone - */ -uint64_t kiro_trb_get_max_elements (KiroTrb* trb); - - -/** - * kiro_trb_get_raw_size - Returns the size of the buffer memory - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns the size of the buffers internal memory - * Notes: - * The returned size is given INCLUDING the header on top of the - * buffers internal memory - * See also: - * kiro_trb_reshape, kiro_trb_adopt, - * kiro_trb_clone - */ -uint64_t kiro_trb_get_raw_size (KiroTrb* trb); - - -/** - * kiro_trb_get_raw_buffer - Returns a pointer to the buffer memory - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns a pointer to the memory structure of the given buffer. - * Notes: - * The returned pointer points to the beginning of the internal - * memory of the buffer, including all header information. The - * user is responsible to ensure the consistency of any data - * written to the memory and should call 'kiro_trb_refesh' in - * case any header information was changed. - * The pointed to memory might become invalid at any time by - * concurrent access to the TRB, reshaping, adopting or cloning - * a new memory block. - * Under no circumstances might the memory pointed to by the returned - * pointer be 'freed' by the user! - * If this function is called on a buffer that is not yet setup, - * a NULL pointer is returned instead. - * See also: - * kiro_trb_refesh, kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone - */ -void* kiro_trb_get_raw_buffer (KiroTrb* trb); - - -/** - * kiro_trb_get_element - Returns a pointer to the element at the given - * index. - * @trb: KIRO TRB to perform the operation on - * @index: Index of the element in the buffer to access - * Description: - * Returns a pointer to the element in the buffer at the given index. - * Notes: - * The returned pointer to the element is only guaranteed to be valid - * immediately after the function call. The user is responsible to - * ensure that no data is written to the returned memory. The - * element pointed to might become invalid at any time by any concurrent - * access to the buffer wraping around and overwriting the element or - * changing the buffer memory entirely. - * Under no circumstances might the memory pointed to by the returned - * pointer be 'freed' by the user! - * If this function is called on a buffer that is not yet setup, - * a NULL pointer is returned instead. - * See also: - * kiro_trb_get_element_size, kiro_trb_get_raw_buffer - */ -void* kiro_trb_get_element (KiroTrb* trb, uint64_t index); - - -/** - * kiro_trb_dma_push - Gives DMA to the next element and pushes the buffer - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns a pointer to the next element in the buffer and increases - * all internal counters and meta data as if an element was pushed - * onto the buffer. - * Notes: - * The returned pointer to the element is only guaranteed to be valid - * immediately after the function call. The user is responsible to - * ensure that no more data is written than 'element_size'. The - * element pointed to might become invalid at any time by any concurrent - * access to the buffer wraping around and overwriting the element or - * changing the buffer memory entirely. - * Under no circumstances might the memory pointed to by the returned - * pointer be 'freed' by the user! - * If this function is called on a buffer that is not yet setup, - * a NULL pointer is returned instead. - * See also: - * kiro_trb_push, kiro_trb_get_element_size, kiro_trb_get_raw_buffer - */ -void* kiro_trb_dma_push (KiroTrb*); - - -/** - * kiro_trb_flush - Resets the buffer - * @trb: KIRO TRB to perform the operation on - * Description: - * Resets the internal buffer structures so the buffer is - * 'empty' again. - * Notes: - * The underlying memory is not cleared, freed or rewritten. - * Only the header is rewritten and the internal pointer and - * counter structures get reset to zero. - * See also: - * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone - */ -void kiro_trb_flush (KiroTrb* trb); - - -/** - * kiro_trb_is_setup - Returns the setup status of the buffer - * @trb: KIRO TRB to perform the operation on - * Description: - * Returns an integer designating of the buffer is ready to - * be used or needs to be 'reshaped' before it can accept data - * Notes: - * A return value of 0 designates that the buffer is not ready - * to be used. Values greater than 0 designate that the buffer - * is setup properly and is ready to accept data. - * See also: - * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone - */ -int kiro_trb_is_setup (KiroTrb* trb); - - -/** - * kiro_trb_reshape - Reallocates internal memory and structures - * @trb: KIRO TRB to perform the operation on - * @element_size: Individual size of the elements to store in bytes - * @element_count: Maximum number of elements to be stored - * Description: - * (Re)Allocates internal memory for the given ammount of elements - * at the given individual size - * Notes: - * If this function gets called when the buffer already has internal - * memory (buffer is setup), that memory gets freed automatically. - * If the function fails (Negative return value) none of the old - * memory and data structures get changed. - * See also: - * kiro_trb_is_setup, kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone - */ -int kiro_trb_reshape (KiroTrb* trb, uint64_t element_size, uint64_t element_count); - - -/** - * kiro_trb_clone - Clones the given memory into the internal memory - * @trb: KIRO TRB to perform the operation on - * @source: Pointer to the source memory to clone from - * Description: - * Interprets the given memory as a pointer to another KIRO TRB and - * tries to copy that memory into its own. - * Notes: - * The given memory is treated as a correct KIRO TRB memory block, - * including a consistend memory header. That header is read and - * then cloned into the internal memory according to the headers - * information. - * If the given memory is not a consistent KIRO TRB memory block, - * the behavior of this function is undefined. - * Returns 0 if the buffer was cloned and -1 if memory allocation - * failed. - * See also: - * kiro_trb_reshape, kiro_trb_adopt - */ -int kiro_trb_clone (KiroTrb* trb, void* source); - - -/** - * kiro_trb_push - Adds an element into the buffer - * @trb: KIRO TRB to perform the operation on - * @source: Pointer to the memory of the element to add - * Description: - * Copies the given element and adds it into the buffer - * Notes: - * This function will read n-Bytes from the given address according - * to the setup element_size. The read memory is copied directly - * into the internal memory structure. - * Returns 0 on success, -1 on failure. - * In case of failure, no internal memory will change as if the - * call to kiro_trb_push has never happened. - * See also: - * kiro_trb_dma_push, kiro_trb_get_element_size, kiro_trb_clone, - * kiro_trb_adopt - */ -int kiro_trb_push (KiroTrb* trb, void* source); - - -/** - * kiro_trb_refresh - Re-reads the TRBs memory header - * @trb: KIRO TRB to perform the operation on - * Description: - * Re-reads the internal memory header and sets up all pointers - * and counters in accordance to these information - * Notes: - * This function is used in case the TRBs memory got changed - * directly (For example, by a DMA operation) to make the TRB - * aware of the changes to its memory. Only the buffers memory - * header is examined and changes are made according to these - * informations. - * See also: - * kiro_trb_get_raw_buffer, kiro_trb_push_dma, kiro_trb_adopt - */ -void kiro_trb_refresh (KiroTrb* trb); - - -/** - * kiro_trb_adopt - Adopts the given memory into the TRB - * @trb: KIRO TRB to perform the operation on - * @source: Pointer to the source memory to adopt - * Description: - * Interprets the given memory as a pointer to another KIRO TRB and - * takes ownership over the memory. - * Notes: - * The given memory is treated as a correct KIRO TRB memory block, - * including a consistend memory header. That header is read and - * the TRB sets up all internal structures in accordance to that - * header. - * If the given memory is not a consistent KIRO TRB memory block, - * the behavior of this function is undefined. - * The TRB takes full ownership of the given memory and may free - * it at will. - * See also: - * kiro_trb_clone, kiro_trb_reshape - */ -void kiro_trb_adopt (KiroTrb* trb, void* source); - -G_END_DECLS - -#endif //__KIRO_TRB_H \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..a657e1c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(kiro kiro-trb.c kiro-client.c kiro-server.c) +target_link_libraries(kiro SDL m rdmacm ibverbs pthread) diff --git a/src/kiro-client.c b/src/kiro-client.c new file mode 100644 index 0000000..807d7d5 --- /dev/null +++ b/src/kiro-client.c @@ -0,0 +1,256 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-client + * @Short_description: KIRO RDMA Client / Consumer + * @Title: KiroClient + * + * KiroClient implements the client / active / consumer side of the the RDMA + * Communication Channel. It uses a KIRO-CLIENT to manage data read from the Server. + */ + +#include +#include +#include +#include +#include +#include +#include "kiro-client.h" +#include "kiro-rdma.h" +#include "kiro-trb.h" + +#include + + +/* + * Definition of 'private' structures and members and macro to access them + */ + +#define KIRO_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_CLIENT, KiroClientPrivate)) + +struct _KiroClientPrivate { + + /* Properties */ + // PLACEHOLDER // + + /* 'Real' private structures */ + /* (Not accessible by properties) */ + struct rdma_event_channel *ec; // Main Event Channel + struct rdma_cm_id *conn; // Connection to the Server + +}; + + +G_DEFINE_TYPE_WITH_PRIVATE (KiroClient, kiro_client, G_TYPE_OBJECT); + + +static void kiro_client_init (KiroClient *self) +{ + KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); + memset(priv, 0, sizeof(&priv)); +} + +static void +kiro_client_finalize (GObject *object) +{ + //KiroClient *self = KIRO_CLIENT(object); + //KiroClientPrivate * priv = KIRO_CLIENT_GET_PRIVATE(self); + //PASS +} + +static void +kiro_client_class_init (KiroClientClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = kiro_client_finalize; +} + + + +int kiro_client_connect (KiroClient *self, char *address, char* port) +{ + KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); + + if(priv->conn) + { + printf("Already connected to server.\n"); + return -1; + } + + struct rdma_addrinfo hints, *res_addrinfo; + memset(&hints, 0, sizeof(hints)); + hints.ai_port_space = RDMA_PS_IB; + if(rdma_getaddrinfo(address, port, &hints, &res_addrinfo)) + { + printf("Failed to contruct address information for %s:%s\n",address, port); + return -1; + } + printf("Address information created.\n"); + + struct ibv_qp_init_attr qp_attr; + memset(&qp_attr, 0, sizeof(qp_attr)); + qp_attr.cap.max_send_wr = 10; + qp_attr.cap.max_recv_wr = 10; + qp_attr.cap.max_send_sge = 1; + qp_attr.cap.max_recv_sge = 1; + qp_attr.qp_context = priv->conn; + qp_attr.sq_sig_all = 1; + + if(rdma_create_ep(&(priv->conn), res_addrinfo, NULL, &qp_attr)) + { + printf("Endpoint creation failed with error: %i\n", errno); + return -1; + } + printf("Route to server resolved.\n"); + + struct kiro_connection_context *ctx = (struct kiro_connection_context *)calloc(1,sizeof(struct kiro_connection_context)); + if(!ctx) + { + printf("Failed to create connection context.\n"); + rdma_destroy_ep(priv->conn); + return -1; + } + + ctx->cf_mr_send = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + ctx->cf_mr_recv = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + if(!ctx->cf_mr_recv || !ctx->cf_mr_send) + { + printf("Failed to allocate Control Flow Memory Container.\n"); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + + ctx->cf_mr_recv = kiro_create_rdma_memory(priv->conn->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); + ctx->cf_mr_send = kiro_create_rdma_memory(priv->conn->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); + if(!ctx->cf_mr_recv || !ctx->cf_mr_send) + { + printf("Failed to register control message memory.\n"); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + ctx->cf_mr_recv->size = ctx->cf_mr_send->size = sizeof(struct kiro_ctrl_msg); + priv->conn->context = ctx; + + if(rdma_post_recv(priv->conn, priv->conn, ctx->cf_mr_recv->mem, ctx->cf_mr_recv->size, ctx->cf_mr_recv->mr)) + { + printf("Posting preemtive receive for connection failed with error: %i\n", errno); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + + if(rdma_connect(priv->conn, NULL)) + { + printf("Failed to establish connection to the server.\n"); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + printf("Connected to server.\n"); + + + struct ibv_wc wc; + if(rdma_get_recv_comp(priv->conn, &wc) < 0) + { + printf("Failure waiting for POST from server.\n"); + rdma_disconnect(priv->conn); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + printf("Got Message from Server.\n"); + ctx->peer_mr = (((struct kiro_ctrl_msg *)(ctx->cf_mr_recv->mem))->peer_mri); + printf("Expected Memory Size is: %u\n",ctx->peer_mr.length); + + ctx->rdma_mr = kiro_create_rdma_memory(priv->conn->pd, ctx->peer_mr.length, IBV_ACCESS_LOCAL_WRITE); + if(!ctx->rdma_mr) + { + printf("Failed to allocate memory for receive buffer.\n"); + rdma_disconnect(priv->conn); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + printf("Connection setup completed successfully!\n"); + + return 0; +} + + + +int kiro_client_sync (KiroClient *self) +{ + KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); + struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; + + if(rdma_post_read(priv->conn, priv->conn, ctx->rdma_mr->mem, ctx->peer_mr.length, ctx->rdma_mr->mr, 0, ctx->peer_mr.addr, ctx->peer_mr.rkey)) + { + printf("Failed to read from server.\n"); + rdma_disconnect(priv->conn); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + + struct ibv_wc wc; + if(rdma_get_send_comp(priv->conn, &wc) < 0) + { + printf("Failure reading from server.\n"); + rdma_disconnect(priv->conn); + kiro_destroy_connection_context(&ctx); + rdma_destroy_ep(priv->conn); + return -1; + } + return 0; +} + + +void* kiro_client_get_memory (KiroClient *self) +{ + KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); + if(!priv->conn) + return NULL; + + struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; + if(!ctx->rdma_mr) + return NULL; + + return ctx->rdma_mr->mem; +} + + +size_t kiro_client_get_memory_size (KiroClient *self) +{ + KiroClientPrivate *priv = KIRO_CLIENT_GET_PRIVATE(self); + if(!priv->conn) + return 0; + + struct kiro_connection_context *ctx = (struct kiro_connection_context *)priv->conn->context; + if(!ctx->rdma_mr) + return 0; + + return ctx->rdma_mr->size; +} + + + + + diff --git a/src/kiro-client.h b/src/kiro-client.h new file mode 100644 index 0000000..e3e60de --- /dev/null +++ b/src/kiro-client.h @@ -0,0 +1,90 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-client + * @Short_description: KIRO RDMA Client / Consumer + * @Title: KiroClient + * + * KiroClient implements the client / active / consumer side of the the RDMA + * Communication Channel. It uses a KIRO-CLIENT to manage data read from the Server. + */ + +#ifndef __KIRO_CLIENT_H +#define __KIRO_CLIENT_H + +#include +#include + +G_BEGIN_DECLS + +#define KIRO_TYPE_CLIENT (kiro_client_get_type()) +#define KIRO_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_CLIENT, KiroClient)) +#define KIRO_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_CLIENT)) +#define KIRO_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_CLIENT, KiroClientClass)) +#define KIRO_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_CLIENT)) +#define KIRO_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_CLIENT, KiroClientClass)) + + +typedef struct _KiroClient KiroClient; +typedef struct _KiroClientClass KiroClientClass; +typedef struct _KiroClientPrivate KiroClientPrivate; + + +struct _KiroClient { + + GObject parent; + + /*< private >*/ + KiroClientPrivate *priv; +}; + + +/** + * IbvConnectorInterface: + * + * Base interface for IbvConnectors. + */ + +struct _KiroClientClass { + + GObjectClass parent_class; + +}; + + + +/* GObject and GType functions */ +GType kiro_client_get_type (void); + +GObject kiro_client_new (void); + +/* client functions */ + + +int kiro_client_connect (KiroClient* client, char* dest_addr, char* dest_port); + +int kiro_client_sync (KiroClient* client); + +void* kiro_client_get_memory (KiroClient* client); + +size_t kior_client_get_memory_size (KiroClient* client); + +G_END_DECLS + +#endif //__KIRO_CLIENT_H \ No newline at end of file diff --git a/src/kiro-rdma.h b/src/kiro-rdma.h new file mode 100644 index 0000000..fa16fd1 --- /dev/null +++ b/src/kiro-rdma.h @@ -0,0 +1,230 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +#include +#include +#include +#ifndef __KIRO_RDMA_H__ +#define __KIRO_RDMA_H__ + + +#include + + +struct kiro_connection_context { + + // Information and necessary structurs + uint32_t identifier; // Unique Identifier for this connection (Application Specific) + struct kiro_rdma_mem *cf_mr_recv; // Control-Flow Memory Region Receive + struct kiro_rdma_mem *cf_mr_send; // Control-Flow Memory Region Send + struct kiro_rdma_mem *rdma_mr; // Memory Region for RDMA Operations + + struct ibv_mr peer_mr; // RDMA Memory Region Information of the peer + + enum { + KIRO_IDLE, + KIRO_MRI_REQUESTED, // Memory Region Information Requested + KIRO_RDMA_ESTABLISHED, // MRI Exchange complete. RDMA is ready + KIRO_RDMA_ACTIVE // RDMA Operation is being performed + } rdma_state; + +}; + + +struct kiro_connection { + + uint32_t identifier; + struct rdma_cm_id *id; + struct kiro_connection *next; + +}; + + +struct kiro_ctrl_msg { + + enum { + KIRO_REQ_RDMA, // Requesting RDMA Access to/from the peer + KIRO_ACK_RDMA, // acknowledge RDMA Request and provide Memory Region Information + KIRO_REJ_RDMA // RDMA Request rejected :( (peer_mri will be invalid) + } msg_type; + + struct ibv_mr peer_mri; + +}; + + +struct kiro_rdma_mem { + + void *mem; // Pointer to the beginning of the memory block + struct ibv_mr *mr; // Memory Region associated with the memory + size_t size; // Size in Bytes of the memory block + +}; + + +static int kiro_attach_qp (struct rdma_cm_id *id) +{ + if(!id) + return -1; + + id->pd = ibv_alloc_pd(id->verbs); + id->send_cq_channel = ibv_create_comp_channel(id->verbs); + id->recv_cq_channel = id->send_cq_channel; //we use one shared completion channel + id->send_cq = ibv_create_cq(id->verbs, 1, id, id->send_cq_channel, 0); + id->recv_cq = id->send_cq; //we use one shared completion queue + + struct ibv_qp_init_attr qp_attr; + memset(&qp_attr, 0, sizeof(struct ibv_qp_init_attr)); + qp_attr.qp_context = (uintptr_t)id; + qp_attr.send_cq = id->send_cq; + qp_attr.recv_cq = id->recv_cq; + qp_attr.qp_type = IBV_QPT_RC; + qp_attr.cap.max_send_wr = 1; + qp_attr.cap.max_recv_wr = 1; + qp_attr.cap.max_send_sge = 1; + qp_attr.cap.max_recv_sge = 1; + + return rdma_create_qp(id, id->pd, &qp_attr); +} + + +static int kiro_register_rdma_memory (struct ibv_pd *pd, struct ibv_mr **mr, void *mem, size_t mem_size, int access) +{ + + if(mem_size == 0) + { + printf("Cant allocate memory of size '0'.\n"); + return -1; + } + + void *mem_handle = mem; + + if(!mem_handle) + mem_handle = malloc(mem_size); + + if(!mem_handle) + { + printf("Failed to allocate memory [Register Memory]."); + return -1; + } + + *mr = ibv_reg_mr(pd, mem_handle, mem_size, access); + if(!(*mr)) + { + // Memory Registration failed + printf("Failed to register memory region!\n"); + free(mem_handle); + return -1; + } + + return 0; +} + + +static struct kiro_rdma_mem* kiro_create_rdma_memory (struct ibv_pd *pd, size_t mem_size, int access) +{ + if(mem_size == 0) + { + printf("Cant allocate memory of size '0'.\n"); + return NULL; + } + + struct kiro_rdma_mem *krm = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + if(!krm) + { + printf("Failed to create new KIRO RDMA Memory.\n"); + return NULL; + } + + if(kiro_register_rdma_memory(pd, &(krm->mr), krm->mem, mem_size, access)) + { + free(krm); + return NULL; + } + + if(!krm->mem) + krm->mem = krm->mr->addr; + + + return krm; + +} + + +static void kiro_destroy_rdma_memory (struct kiro_rdma_mem *krm) +{ + if(!krm) + return; + + if(krm->mr) + ibv_dereg_mr(krm->mr); + + if(krm->mem) + free(krm->mem); + + free(krm); + krm = NULL; +} + + +static void kiro_destroy_connection_context (struct kiro_connection_context **ctx) +{ + if(!ctx) + return; + + if(!(*ctx)) + return; + + if((*ctx)->cf_mr_recv) + kiro_destroy_rdma_memory((*ctx)->cf_mr_recv); + if((*ctx)->cf_mr_send) + kiro_destroy_rdma_memory((*ctx)->cf_mr_send); + + //The RDMA-Memory Region normally contains allocated memory from the USER that has + //just been 'registered' for RDMA. DON'T free it! Just deregister it. The user is + //responsible for freeing this memory. + if((*ctx)->rdma_mr) + { + if((*ctx)->rdma_mr->mr) + ibv_dereg_mr((*ctx)->rdma_mr->mr); + + free((*ctx)->rdma_mr); + (*ctx)->rdma_mr = NULL; + } + + free(*ctx); + *ctx = NULL; +} + + +static void kiro_destroy_connection (struct rdma_cm_id **conn) +{ + if(!(*conn)) + return; + + rdma_disconnect(*conn); + struct kiro_connection_context *ctx = (struct kiro_connection_context *)((*conn)->context); + if(ctx) + kiro_destroy_connection_context(&ctx); + + rdma_destroy_ep(*conn); + *conn = NULL; +} + + +#endif //__KIRO_RDMA_H__ \ No newline at end of file diff --git a/src/kiro-server.c b/src/kiro-server.c new file mode 100644 index 0000000..52304c8 --- /dev/null +++ b/src/kiro-server.c @@ -0,0 +1,361 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-server + * @Short_description: KIRO RDMA Server / Consumer + * @Title: KiroServer + * + * KiroServer implements the server / passive / provider side of the the RDMA + * Communication Channel. It uses a KIRO-TRB to manage its data. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "kiro-server.h" +#include "kiro-rdma.h" +#include "kiro-trb.h" + + +/* + * Definition of 'private' structures and members and macro to access them + */ + +#define KIRO_SERVER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_SERVER, KiroServerPrivate)) + +struct _KiroServerPrivate { + + /* Properties */ + // PLACEHOLDER // + + /* 'Real' private structures */ + /* (Not accessible by properties) */ + struct rdma_event_channel *ec; // Main Event Channel + struct rdma_cm_id *base; // Base-Listening-Connection + struct kiro_connection *client; // Connection to the client + pthread_t event_listener; // Pointer to the completion-listener thread of this connection + pthread_mutex_t mtx; // Mutex to signal the listener-thread termination + void *mem; // Pointer to the server buffer + size_t mem_size; // Server Buffer Size in bytes + +}; + + +G_DEFINE_TYPE_WITH_PRIVATE (KiroServer, kiro_server, G_TYPE_OBJECT); + + +static void kiro_server_init (KiroServer *self) +{ + KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE(self); + memset(priv, 0, sizeof(&priv)); +} + + +static void +kiro_server_finalize (GObject *object) +{ + //PASS +} + + +static void +kiro_server_class_init (KiroServerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = kiro_server_finalize; +} + + +static int connect_client (struct rdma_cm_id *client) +{ + if(!client) + return -1; + + if( -1 == kiro_attach_qp(client)) + { + printf("Could not create a QP for the new connection.\n"); + rdma_destroy_id(client); + return -1; + } + + struct kiro_connection_context *ctx = (struct kiro_connection_context *)calloc(1,sizeof(struct kiro_connection_context)); + if(!ctx) + { + printf("Failed to create connection context.\n"); + rdma_destroy_id(client); + return -1; + } + + ctx->cf_mr_send = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + ctx->cf_mr_recv = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + if(!ctx->cf_mr_recv || !ctx->cf_mr_send) + { + printf("Failed to allocate Control Flow Memory Container.\n"); + goto error; + } + + ctx->cf_mr_recv = kiro_create_rdma_memory(client->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); + ctx->cf_mr_send = kiro_create_rdma_memory(client->pd, sizeof(struct kiro_ctrl_msg), IBV_ACCESS_LOCAL_WRITE); + if(!ctx->cf_mr_recv || !ctx->cf_mr_send) + { + printf("Failed to register control message memory.\n"); + goto error; + } + ctx->cf_mr_recv->size = ctx->cf_mr_send->size = sizeof(struct kiro_ctrl_msg); + client->context = ctx; + + if(rdma_post_recv(client, client, ctx->cf_mr_recv->mem, ctx->cf_mr_recv->size, ctx->cf_mr_recv->mr)) + { + printf("Posting preemtive receive for connection failed.\n"); + goto error; + } + + if(rdma_accept(client, NULL)) + { + printf("Failed to establish connection to the client with error: %i.\n", errno); + goto error; + } + printf("Client Connected.\n"); + return 0; + + +error: + rdma_reject(client, NULL, 0); + kiro_destroy_connection_context(&ctx); + rdma_destroy_id(client); + return -1; +} + + +static int welcome_client (struct rdma_cm_id *client, void *mem, size_t mem_size) +{ + struct kiro_connection_context *ctx = (struct kiro_connection_context *)(client->context); + ctx->rdma_mr = (struct kiro_rdma_mem *)calloc(1, sizeof(struct kiro_rdma_mem)); + if(!ctx->rdma_mr) + { + printf("Failed to allocate RDMA Memory Container.\n"); + return -1; + } + + ctx->rdma_mr->mem = mem; + ctx->rdma_mr->size = mem_size; + ctx->rdma_mr->mr = rdma_reg_read(client, ctx->rdma_mr->mem, ctx->rdma_mr->size); + if(!ctx->rdma_mr->mr) + { + printf("Failed to register RDMA Memory Region.\n"); + kiro_destroy_rdma_memory(ctx->rdma_mr); + return -1; + } + + struct kiro_ctrl_msg *msg = (struct kiro_ctrl_msg *)(ctx->cf_mr_send->mem); + msg->msg_type = KIRO_ACK_RDMA; + msg->peer_mri = *(ctx->rdma_mr->mr); + + if(rdma_post_send(client, client, ctx->cf_mr_send->mem, ctx->cf_mr_send->size, ctx->cf_mr_send->mr, IBV_SEND_SIGNALED)) + { + printf("Failure while trying to post SEND.\n"); + kiro_destroy_rdma_memory(ctx->rdma_mr); + return -1; + } + + struct ibv_wc wc; + + if(rdma_get_send_comp(client, &wc) < 0) + { + printf("Failed to post RDMA MRI to client.\n"); + kiro_destroy_rdma_memory(ctx->rdma_mr); + return -1; + } + printf("RDMA MRI sent to client.\n"); + + return 0; +} + + +void * event_loop (void *self) +{ + KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE((KiroServer *)self); + struct rdma_cm_event *active_event; + + int stop = 0; + + while(0 == stop) { + if(0 <= rdma_get_cm_event(priv->ec, &active_event)) + { + + struct rdma_cm_event *ev = malloc(sizeof(*active_event)); + if(!ev) + { + printf("Unable to allocate memory for Event handling!\n"); + rdma_ack_cm_event(active_event); + continue; + } + memcpy(ev, active_event, sizeof(*active_event)); + rdma_ack_cm_event(active_event); + + if (ev->event == RDMA_CM_EVENT_CONNECT_REQUEST) + { + + /* + priv->client = (struct kiro_connection *)calloc(1, sizeof(struct kiro_connection)); + if(!(priv->client)) + { + printf("Failed to create container for client connection.\n"); + free(ev); + continue; + } + priv->client->identifier = 0; //First Client + priv->client->id = ev->id; + */ + + if(0 == connect_client(ev->id)) + { + // Connection set-up successfully! (Server) + // Post a welcoming "Recieve" for handshaking + welcome_client(ev->id, priv->mem, priv->mem_size); + } + } + else if(ev->event == RDMA_CM_EVENT_DISCONNECTED) + { + printf("Got disconnect request.\n"); + //pthread_mutex_unlock(&(priv->mtx)); + kiro_destroy_connection(&(ev->id)); + printf("Connection closed successfully\n"); + } + free(ev); + } + + // Mutex will be freed as a signal to stop request + if(0 == pthread_mutex_trylock(&(priv->mtx))) + stop = 1; + } + + printf("Closing Event Listener Thread\n"); + return NULL; +} + + + + +int kiro_server_start (KiroServer *self, char *address, char *port, void* mem, size_t mem_size) +{ + KiroServerPrivate *priv = KIRO_SERVER_GET_PRIVATE(self); + + if(priv->base) + { + printf("Server already started.\n"); + return -1; + } + + if(!mem || mem_size == 0) + { + printf("Invalid memory given to provide.\n"); + return -1; + } + + struct rdma_addrinfo hints, *res_addrinfo; + memset(&hints, 0, sizeof(hints)); + hints.ai_port_space = RDMA_PS_IB; + hints.ai_flags = RAI_PASSIVE; + if(rdma_getaddrinfo(address, port, &hints, &res_addrinfo)) + { + printf("Failed to create address information."); + return -1; + } + + struct ibv_qp_init_attr qp_attr; + memset(&qp_attr, 0, sizeof(qp_attr)); + qp_attr.cap.max_send_wr = 10; + qp_attr.cap.max_recv_wr = 10; + qp_attr.cap.max_send_sge = 1; + qp_attr.cap.max_recv_sge = 1; + qp_attr.qp_context = priv->base; + qp_attr.sq_sig_all = 1; + + if(rdma_create_ep(&(priv->base), res_addrinfo, NULL, &qp_attr)) + { + printf("Endpoint creation failed.\n"); + return -1; + } + printf("Endpoint created.\n"); + + char *addr_local = NULL; + struct sockaddr* src_addr = rdma_get_local_addr(priv->base); + if(!src_addr) + { + addr_local = "NONE"; + } + else + { + addr_local = inet_ntoa(((struct sockaddr_in *)src_addr)->sin_addr); + /* + if(src_addr->sa_family == AF_INET) + addr_local = &(((struct sockaddr_in*)src_addr)->sin_addr); + else + addr_local = &(((struct sockaddr_in6*)src_addr)->sin6_addr); + */ + } + + printf("Bound to address %s:%s\n",addr_local, port); + + if(rdma_listen(priv->base, 0)) + { + printf("Failed to put server into listening state.\n"); + rdma_destroy_ep(priv->base); + return -1; + } + + priv->mem = mem; + priv->mem_size = mem_size; + + priv->ec = rdma_create_event_channel(); + int oldflags = fcntl (priv->ec->fd, F_GETFL, 0); + /* Only change the FD Mode if we were able to get its flags */ + if (oldflags >= 0) { + oldflags |= O_NONBLOCK; + /* Store modified flag word in the descriptor. */ + fcntl (priv->ec->fd, F_SETFL, oldflags); + } + if(rdma_migrate_id(priv->base, priv->ec)) + { + printf("Was unable to migrate connection to new Event Channel.\n"); + rdma_destroy_ep(priv->base); + return -1; + } + + pthread_mutex_init(&(priv->mtx), NULL); + pthread_mutex_lock(&(priv->mtx)); + pthread_create(&(priv->event_listener), NULL, event_loop, self); + + printf("Enpoint listening.\n"); + + sleep(1); + return 0; +} + + + + + + + diff --git a/src/kiro-server.h b/src/kiro-server.h new file mode 100644 index 0000000..cb9b57c --- /dev/null +++ b/src/kiro-server.h @@ -0,0 +1,106 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-server + * @Short_description: KIRO RDMA Server / Consumer + * @Title: KiroServer + * + * KiroServer implements the server / passive / provider side of the the RDMA + * Communication Channel. It uses a KIRO-TRB to manage its data. + */ + +#ifndef __KIRO_SERVER_H +#define __KIRO_SERVER_H + +#include +#include + +G_BEGIN_DECLS + +#define KIRO_TYPE_SERVER (kiro_server_get_type()) +#define KIRO_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_SERVER, KiroServer)) +#define KIRO_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_SERVER)) +#define KIRO_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_SERVER, KiroServerClass)) +#define KIRO_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_SERVER)) +#define KIRO_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_SERVER, KiroServerClass)) + + +typedef struct _KiroServer KiroServer; +typedef struct _KiroServerClass KiroServerClass; +typedef struct _KiroServerPrivate KiroServerPrivate; + + +struct _KiroServer { + + GObject parent; + + /*< private >*/ + KiroServerPrivate *priv; +}; + + +/** + * IbvConnectorInterface: + * + * Base interface for IbvConnectors. + */ + +struct _KiroServerClass { + + GObjectClass parent_class; + +}; + + + +/* GObject and GType functions */ +GType kiro_server_get_type (void); + +GObject kiro_server_new (void); + +/* server functions */ + +/** + * kiro_server_start - Starts the server, providing the given memory + * @server: KIRO SERVER to perform the operation on + * @bind_addr: Local address to bind the server to + * @bind_port: Local port to listen for connections + * @mem: Pointer to the memory that is to be provided + * @mem_size: Size in bytes of the given memory + * Description: + * Starts the server to provide the given memory to any connecting + * client. + * Notes: + * If the bind_addr is NULL, the server will bind to the first device + * it can find on the machine and listen across all IPs. Otherwise it + * will try to bind to the device associated with the given address. + * Address is given as a string of either a hostname or a dot-seperated + * IPv4 address or a colon-seperated IPv6 hex-address. + * If bind_port is NULL the server will choose a free port randomly + * and return the chosen port as return value. + * If server creation fails, -1 is returned instead. + * See also: + * kiro_trb_reshape, kiro_trb_adopt, + * kiro_trb_clone + */ +int kiro_server_start (KiroServer* server, char* bind_addr, char* bind_port, void* mem, size_t mem_size); + +G_END_DECLS + +#endif //__KIRO_SERVER_H \ No newline at end of file diff --git a/src/kiro-trb.c b/src/kiro-trb.c new file mode 100644 index 0000000..e81a4f7 --- /dev/null +++ b/src/kiro-trb.c @@ -0,0 +1,270 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-trb + * @Short_description: KIRO 'Transmittable Ring Buffer' + * @Title: KiroTrb + * + * KiroTrb implements a 'Transmittable Ring Buffer' that holds all necessary information + * about its content inside itself, so its data can be exchanged between different + * instances of the KiroTrb Class and/or sent over a network. + */ + +#include + +#include +#include +#include +#include "kiro-trb.h" + + +/* + * Definition of 'private' structures and members and macro to access them + */ + +#define KIRO_TRB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), KIRO_TYPE_TRB, KiroTrbPrivate)) + +struct _KiroTrbPrivate { + + /* Properties */ + // PLACEHOLDER // + + /* 'Real' private structures */ + /* (Not accessible by properties) */ + int initialized; // 1 if Buffer is Valid, 0 otherwise + void *mem; // Access to the actual buffer in Memory + void *frame_top; // First byte of the buffer storage + void *current; // Pointer to the current fill state + uint64_t element_size; + uint64_t max_elements; + uint64_t iteration; // How many times the buffer has wraped around + + /* easy access */ + uint64_t buff_size; +}; + + +G_DEFINE_TYPE_WITH_PRIVATE (KiroTrb, kiro_trb, G_TYPE_OBJECT); + + +static +void kiro_trb_init (KiroTrb *self) +{ + KiroTrbPrivate *priv = KIRO_TRB_GET_PRIVATE(self); + priv->initialized = 0; +} + +static void +kiro_trb_finalize (GObject *object) +{ + KiroTrb *self = KIRO_TRB(object); + KiroTrbPrivate *priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->mem) + free(priv->mem); +} + +static void +kiro_trb_class_init (KiroTrbClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = kiro_trb_finalize; +} + + +/* Privat functions */ + +void write_header (KiroTrbPrivate* priv) +{ + if(!priv) + return; + struct KiroTrbInfo* tmp_info = (struct KiroTrbInfo*)priv->mem; + tmp_info->buffer_size_bytes = priv->buff_size; + tmp_info->element_size = priv->element_size; + tmp_info->offset = (priv->iteration * priv->max_elements) + ((priv->current - priv->frame_top) / priv->element_size); + memcpy(priv->mem, tmp_info, sizeof(struct KiroTrbInfo)); +} + + + +/* TRB functions */ + +uint64_t kiro_trb_get_element_size (KiroTrb* self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return 0; + return priv->element_size; +} + + +uint64_t kiro_trb_get_max_elements (KiroTrb* self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return 0; + return priv->max_elements; +} + + +uint64_t kiro_trb_get_raw_size (KiroTrb* self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return 0; + return priv->buff_size; +} + + +void* kiro_trb_get_raw_buffer (KiroTrb* self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return NULL; + write_header(priv); + return priv->mem; +} + + + +void* kiro_trb_get_element (KiroTrb* self, uint64_t element) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return NULL; + + uint64_t relative = 0; + if(priv->iteration == 0) + relative = element * priv->element_size; + else + relative = ((priv->current - priv->frame_top) + (priv->element_size * element)) % (priv->buff_size - sizeof(struct KiroTrbInfo)); + + return priv->frame_top + relative; +} + + +void kiro_trb_flush (KiroTrb *self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + priv->iteration = 0; + priv->current = priv->frame_top; + write_header(priv); +} + + +int kiro_trb_is_setup (KiroTrb *self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + return priv->initialized; +} + + +int kiro_trb_reshape (KiroTrb *self, uint64_t element_size, uint64_t element_count) +{ + size_t new_size = (element_size * element_count) + sizeof(struct KiroTrbInfo); + void* newmem = malloc(new_size); + if(!newmem) + return -1; + ((struct KiroTrbInfo *)newmem)->buffer_size_bytes = new_size; + ((struct KiroTrbInfo *)newmem)->element_size = element_size; + ((struct KiroTrbInfo *)newmem)->offset = 0; + kiro_trb_adopt(self, newmem); + return 0; +} + + +int kiro_trb_push (KiroTrb *self, void *element_in) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return -1; + if((priv->current + priv->element_size) > (priv->mem + priv->buff_size)) + return -1; + memcpy(priv->current, element_in, priv->element_size); + priv->current += priv->element_size; + if(priv->current >= priv->frame_top + (priv->element_size * priv->max_elements)) + { + priv->current = priv->frame_top; + priv->iteration++; + } + write_header(priv); + return 0; +} + + +void* kiro_trb_dma_push (KiroTrb *self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return NULL; + if((priv->current + priv->element_size) > (priv->mem + priv->buff_size)) + return NULL; + void *mem_out = priv->current; + priv->current += priv->element_size; + if(priv->current >= priv->frame_top + (priv->element_size * priv->max_elements)) + { + priv->current = priv->frame_top; + priv->iteration++; + } + write_header(priv); + return mem_out; +} + + +void kiro_trb_refresh (KiroTrb *self) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->initialized != 1) + return; + struct KiroTrbInfo *tmp = (struct KiroTrbInfo *)priv->mem; + priv->buff_size = tmp->buffer_size_bytes; + priv->element_size = tmp->element_size; + priv->max_elements = (tmp->buffer_size_bytes - sizeof(struct KiroTrbInfo)) / tmp->element_size; + priv->iteration = tmp->offset / priv->max_elements; + priv->frame_top = priv->mem + sizeof(struct KiroTrbInfo); + priv->current = priv->frame_top + ((tmp->offset % priv->max_elements) * priv->element_size); + priv->initialized = 1; +} + + +void kiro_trb_adopt (KiroTrb *self, void *buff_in) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + if(priv->mem) + free(priv->mem); + priv->mem = buff_in; + priv->initialized = 1; + kiro_trb_refresh(self); +} + + +int kiro_trb_clone (KiroTrb *self, void *buff_in) +{ + KiroTrbPrivate* priv = KIRO_TRB_GET_PRIVATE(self); + struct KiroTrbInfo *header = (struct KiroTrbInfo *)buff_in; + void *newmem = malloc(header->buffer_size_bytes); + if(!newmem) + return -1; + memcpy(newmem, buff_in, header->buffer_size_bytes); + if(priv->mem) + free(priv->mem); + priv->mem = newmem; + priv->initialized = 1; + kiro_trb_refresh(self); + return 0; +} diff --git a/src/kiro-trb.h b/src/kiro-trb.h new file mode 100644 index 0000000..5c2b462 --- /dev/null +++ b/src/kiro-trb.h @@ -0,0 +1,332 @@ +/* Copyright (C) 2014 Timo Dritschler + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA +*/ + +/** + * SECTION: kiro-trb + * @Short_description: KIRO 'Transmittable Ring Buffer' + * @Title: KiroTrb + * + * KiroTrb implements a 'Transmittable Ring Buffer' that holds all necessary information + * about its content inside itself, so its data can be exchanged between different + * instances of the KiroTrb Class and/or sent over a network. + */ + +#ifndef __KIRO_TRB_H +#define __KIRO_TBR_H + +#include +#include + +G_BEGIN_DECLS + +#define KIRO_TYPE_TRB (kiro_trb_get_type()) +#define KIRO_TRB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KIRO_TYPE_TRB, KiroTrb)) +#define KIRO_IS_TRB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KIRO_TYPE_TRB)) +#define KIRO_TRB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), KIRO_TYPE_TRB, KiroTrbClass)) +#define KIRO_IS_TRB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), KIRO_TYPE_TRB)) +#define KIRO_TRB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), KIRO_TYPE_TRB, KiroTrbClass)) + + +typedef struct _KiroTrb KiroTrb; +typedef struct _KiroTrbClass KiroTrbClass; +typedef struct _KiroTrbPrivate KiroTrbPrivate; + + +struct _KiroTrb { + + GObject parent; + +}; + + +/** + * IbvConnectorInterface: + * + * Base interface for IbvConnectors. + */ + +struct _KiroTrbClass { + + GObjectClass parent_class; + +}; + + +struct KiroTrbInfo { + + /* internal information about the buffer */ + uint64_t buffer_size_bytes; // Size in bytes INCLUDING this header + uint64_t element_size; // Size in bytes of one single element + uint64_t offset; // Current Offset to access the 'oldest' element (in element count!) + +} __attribute__((packed)); + + +/* GObject and GType functions */ +GType kiro_trb_get_type (void); + +GObject kiro_trb_new (void); + + +/* trb functions */ + +/** + * kiro_trb_get_element_size - Returns the element size in bytes + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns the size of the individual elements in the buffer + * See also: + * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone + */ +uint64_t kiro_trb_get_element_size (KiroTrb* trb); + +/** + * kiro_trb_get_max_elements - Returns the capacity of the buffer + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns the mximal number of elements that can be stored in + * the buffer + * See also: + * kiro_trb_get_element_size, kiro_trb_reshape, kiro_trb_adopt, + * kiro_trb_clone + */ +uint64_t kiro_trb_get_max_elements (KiroTrb* trb); + + +/** + * kiro_trb_get_raw_size - Returns the size of the buffer memory + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns the size of the buffers internal memory + * Notes: + * The returned size is given INCLUDING the header on top of the + * buffers internal memory + * See also: + * kiro_trb_reshape, kiro_trb_adopt, + * kiro_trb_clone + */ +uint64_t kiro_trb_get_raw_size (KiroTrb* trb); + + +/** + * kiro_trb_get_raw_buffer - Returns a pointer to the buffer memory + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns a pointer to the memory structure of the given buffer. + * Notes: + * The returned pointer points to the beginning of the internal + * memory of the buffer, including all header information. The + * user is responsible to ensure the consistency of any data + * written to the memory and should call 'kiro_trb_refesh' in + * case any header information was changed. + * The pointed to memory might become invalid at any time by + * concurrent access to the TRB, reshaping, adopting or cloning + * a new memory block. + * Under no circumstances might the memory pointed to by the returned + * pointer be 'freed' by the user! + * If this function is called on a buffer that is not yet setup, + * a NULL pointer is returned instead. + * See also: + * kiro_trb_refesh, kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone + */ +void* kiro_trb_get_raw_buffer (KiroTrb* trb); + + +/** + * kiro_trb_get_element - Returns a pointer to the element at the given + * index. + * @trb: KIRO TRB to perform the operation on + * @index: Index of the element in the buffer to access + * Description: + * Returns a pointer to the element in the buffer at the given index. + * Notes: + * The returned pointer to the element is only guaranteed to be valid + * immediately after the function call. The user is responsible to + * ensure that no data is written to the returned memory. The + * element pointed to might become invalid at any time by any concurrent + * access to the buffer wraping around and overwriting the element or + * changing the buffer memory entirely. + * Under no circumstances might the memory pointed to by the returned + * pointer be 'freed' by the user! + * If this function is called on a buffer that is not yet setup, + * a NULL pointer is returned instead. + * See also: + * kiro_trb_get_element_size, kiro_trb_get_raw_buffer + */ +void* kiro_trb_get_element (KiroTrb* trb, uint64_t index); + + +/** + * kiro_trb_dma_push - Gives DMA to the next element and pushes the buffer + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns a pointer to the next element in the buffer and increases + * all internal counters and meta data as if an element was pushed + * onto the buffer. + * Notes: + * The returned pointer to the element is only guaranteed to be valid + * immediately after the function call. The user is responsible to + * ensure that no more data is written than 'element_size'. The + * element pointed to might become invalid at any time by any concurrent + * access to the buffer wraping around and overwriting the element or + * changing the buffer memory entirely. + * Under no circumstances might the memory pointed to by the returned + * pointer be 'freed' by the user! + * If this function is called on a buffer that is not yet setup, + * a NULL pointer is returned instead. + * See also: + * kiro_trb_push, kiro_trb_get_element_size, kiro_trb_get_raw_buffer + */ +void* kiro_trb_dma_push (KiroTrb*); + + +/** + * kiro_trb_flush - Resets the buffer + * @trb: KIRO TRB to perform the operation on + * Description: + * Resets the internal buffer structures so the buffer is + * 'empty' again. + * Notes: + * The underlying memory is not cleared, freed or rewritten. + * Only the header is rewritten and the internal pointer and + * counter structures get reset to zero. + * See also: + * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone + */ +void kiro_trb_flush (KiroTrb* trb); + + +/** + * kiro_trb_is_setup - Returns the setup status of the buffer + * @trb: KIRO TRB to perform the operation on + * Description: + * Returns an integer designating of the buffer is ready to + * be used or needs to be 'reshaped' before it can accept data + * Notes: + * A return value of 0 designates that the buffer is not ready + * to be used. Values greater than 0 designate that the buffer + * is setup properly and is ready to accept data. + * See also: + * kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone + */ +int kiro_trb_is_setup (KiroTrb* trb); + + +/** + * kiro_trb_reshape - Reallocates internal memory and structures + * @trb: KIRO TRB to perform the operation on + * @element_size: Individual size of the elements to store in bytes + * @element_count: Maximum number of elements to be stored + * Description: + * (Re)Allocates internal memory for the given ammount of elements + * at the given individual size + * Notes: + * If this function gets called when the buffer already has internal + * memory (buffer is setup), that memory gets freed automatically. + * If the function fails (Negative return value) none of the old + * memory and data structures get changed. + * See also: + * kiro_trb_is_setup, kiro_trb_reshape, kiro_trb_adopt, kiro_trb_clone + */ +int kiro_trb_reshape (KiroTrb* trb, uint64_t element_size, uint64_t element_count); + + +/** + * kiro_trb_clone - Clones the given memory into the internal memory + * @trb: KIRO TRB to perform the operation on + * @source: Pointer to the source memory to clone from + * Description: + * Interprets the given memory as a pointer to another KIRO TRB and + * tries to copy that memory into its own. + * Notes: + * The given memory is treated as a correct KIRO TRB memory block, + * including a consistend memory header. That header is read and + * then cloned into the internal memory according to the headers + * information. + * If the given memory is not a consistent KIRO TRB memory block, + * the behavior of this function is undefined. + * Returns 0 if the buffer was cloned and -1 if memory allocation + * failed. + * See also: + * kiro_trb_reshape, kiro_trb_adopt + */ +int kiro_trb_clone (KiroTrb* trb, void* source); + + +/** + * kiro_trb_push - Adds an element into the buffer + * @trb: KIRO TRB to perform the operation on + * @source: Pointer to the memory of the element to add + * Description: + * Copies the given element and adds it into the buffer + * Notes: + * This function will read n-Bytes from the given address according + * to the setup element_size. The read memory is copied directly + * into the internal memory structure. + * Returns 0 on success, -1 on failure. + * In case of failure, no internal memory will change as if the + * call to kiro_trb_push has never happened. + * See also: + * kiro_trb_dma_push, kiro_trb_get_element_size, kiro_trb_clone, + * kiro_trb_adopt + */ +int kiro_trb_push (KiroTrb* trb, void* source); + + +/** + * kiro_trb_refresh - Re-reads the TRBs memory header + * @trb: KIRO TRB to perform the operation on + * Description: + * Re-reads the internal memory header and sets up all pointers + * and counters in accordance to these information + * Notes: + * This function is used in case the TRBs memory got changed + * directly (For example, by a DMA operation) to make the TRB + * aware of the changes to its memory. Only the buffers memory + * header is examined and changes are made according to these + * informations. + * See also: + * kiro_trb_get_raw_buffer, kiro_trb_push_dma, kiro_trb_adopt + */ +void kiro_trb_refresh (KiroTrb* trb); + + +/** + * kiro_trb_adopt - Adopts the given memory into the TRB + * @trb: KIRO TRB to perform the operation on + * @source: Pointer to the source memory to adopt + * Description: + * Interprets the given memory as a pointer to another KIRO TRB and + * takes ownership over the memory. + * Notes: + * The given memory is treated as a correct KIRO TRB memory block, + * including a consistend memory header. That header is read and + * the TRB sets up all internal structures in accordance to that + * header. + * If the given memory is not a consistent KIRO TRB memory block, + * the behavior of this function is undefined. + * The TRB takes full ownership of the given memory and may free + * it at will. + * See also: + * kiro_trb_clone, kiro_trb_reshape + */ +void kiro_trb_adopt (KiroTrb* trb, void* source); + +G_END_DECLS + +#endif //__KIRO_TRB_H \ No newline at end of file diff --git a/test-client.c b/test-client.c deleted file mode 100644 index 469aa5e..0000000 --- a/test-client.c +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include -#include "kiro-client.h" -#include "kiro-trb.h" -#include -#include - - -static _Bool init_app(const char * name, SDL_Surface * icon, uint32_t flags) -{ - atexit(SDL_Quit); - if(SDL_Init(flags) < 0) - return 0; - - SDL_WM_SetCaption(name, name); - SDL_WM_SetIcon(icon, NULL); - - return 1; -} - -static void render(SDL_Surface * sf) -{ - SDL_Surface * screen = SDL_GetVideoSurface(); - if(SDL_BlitSurface(sf, NULL, screen, NULL) == 0) - SDL_UpdateRect(screen, 0, 0, 0, 0); -} - -static int filter(const SDL_Event * event) -{ return event->type == SDL_QUIT; } - - -int main ( int argc, char *argv[] ) -{ - if (argc < 3) - { - printf("Not enough aruments. Usage: ./client
\n"); - return -1; - } - KiroClient *client = g_object_new(KIRO_TYPE_CLIENT, NULL); - if(-1 == kiro_client_connect(client, argv[1], argv[2])) - { - g_object_unref(client); - return -1; - } - - kiro_client_sync(client); - KiroTrb *trb = g_object_new(KIRO_TYPE_TRB, NULL); - kiro_trb_adopt(trb, kiro_client_get_memory(client)); - - _Bool ok = - init_app("UCA Images", NULL, SDL_INIT_VIDEO) && - SDL_SetVideoMode(512, 512, 8, SDL_HWSURFACE); - - assert(ok); - - uint32_t mask = 0xffffffff; - SDL_Surface * data_sf = SDL_CreateRGBSurfaceFrom( - kiro_trb_get_element(trb, 0), 512, 512, 8, 512, - mask, mask, mask, 0); - - SDL_Color colors[256]; - for(int i=0;i<256;i++){ - colors[i].r=i; - colors[i].g=i; - colors[i].b=i; - } - SDL_SetPalette(data_sf, SDL_LOGPAL|SDL_PHYSPAL, colors, 0, 256); - - SDL_SetEventFilter(filter); - - int cont = 1; - - //struct KiroTrbInfo *header = (struct KiroTrbInfo *)kiro_trb_get_raw_buffer(trb); - - while(cont) - { - for(SDL_Event event; SDL_PollEvent(&event);) - if(event.type == SDL_QUIT) cont=0; - - kiro_client_sync(client); - SDL_Delay(10); - render(data_sf); - } - - - g_object_unref(client); - return 0; -} - - - - - - - - diff --git a/test-server.c b/test-server.c deleted file mode 100644 index 63fefaa..0000000 --- a/test-server.c +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include "kiro-server.h" -#include "kiro-trb.h" -#include -#include -#include -#include - - - -static const char g_digits[10][20] = { - /* 0 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 1 */ - { 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x00 }, - /* 2 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff }, - /* 3 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 4 */ - { 0xff, 0x00, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff }, - /* 5 */ - { 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0x00 }, - /* 6 */ - { 0x00, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 7 */ - { 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x00 }, - /* 8 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0x00 }, - /* 9 */ - { 0x00, 0xff, 0xff, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0x00 } -}; - -static const guint DIGIT_WIDTH = 4; -static const guint DIGIT_HEIGHT = 5; - -static void -print_number (gchar *buffer, guint number, guint x, guint y, guint width) -{ - for (int i = 0; i < DIGIT_WIDTH; i++) { - for (int j = 0; j < DIGIT_HEIGHT; j++) { - char val = (char) g_digits[number][j*DIGIT_WIDTH+i]; - if(val != 0x00) { - //This should make the frame counter appear in a bright yellow - val = 0xBE; - } - buffer[(y+j)*width + (x+i)] = (guint8) val; - } - } -} - -static void -print_current_frame (gchar *buffer, guint number, guint width, guint height, GRand *rand) -{ - guint divisor = 10000000; - int x = 1; - - while (divisor > 0) { - print_number(buffer, number / divisor, x, 1, width); - number = number % divisor; - divisor = divisor / 10; - x += DIGIT_WIDTH + 1; - } - - - //Rainbow pattern is the same for every row. Just calculate one single - //Scanline, so we can reuse it and dont have to do the whole calculation - //for every row again. - char default_line[width]; - for (int p = 0; p < width; p++) { - default_line[p] = (char) ((p*256) / (width)); - } - - - //Use memcpy to quickly fill every row with the precalculated rainbow - //pattern - for (guint y = 16; y < height; y++) { - guint index = y * width; - memcpy(buffer+index, &default_line[0], width); - } - - //This block will fill a square at the center of the image with normal - //distributed random data - const double mean = 128.0; - const double std = 32.0; - - for (guint y = (height/3); y < ((height*2)/3); y++) { - guint row_start = y * width; - for (guint i = (width/3); i < ((width*2)/3); i++) { - int index = row_start + i; - double u1 = g_rand_double(rand); - double u2 = g_rand_double(rand); - double r = sqrt(-2 * log(u1)) * cos(2 * G_PI * u2); - buffer[index] = (guint8) (r * std + mean); - } - } -} - - -int main(void) -{ - KiroServer *server = g_object_new(KIRO_TYPE_SERVER, NULL); - KiroTrb *rb = g_object_new(KIRO_TYPE_TRB, NULL); - kiro_trb_reshape(rb, 512*512, 15); - GRand *rand = g_rand_new(); - if(0 > kiro_server_start(server, NULL, "60010", kiro_trb_get_raw_buffer(rb), kiro_trb_get_raw_size(rb))) - { - printf("Failed to start server properly.\n"); - goto done; - } - - guint frame = 0; - gchar *buffer = NULL; - while(1) - { - buffer = kiro_trb_dma_push(rb); - print_current_frame(buffer, frame, 512, 512, rand); - frame++; - } - -done: - g_rand_free(rand); - g_object_unref(rb); - - return 0; -} \ No newline at end of file diff --git a/test.c b/test.c deleted file mode 100644 index 4aac2f5..0000000 --- a/test.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include "kiro-trb.h" - -struct test { - uint32_t zahl; - uint8_t buchstabe; -} __attribute__((packed)); - - -int main(void) -{ - /* - void* ptr = malloc(sizeof(struct test) + sizeof(uint64_t)); - memset(ptr, 0xFA, sizeof(struct test) + sizeof(uint64_t)); - struct test foo; - foo.zahl = 42; - foo.buchstabe = 'R'; - memcpy(ptr, &foo, sizeof(foo)); - - struct test *tmp = (struct test *)ptr; - printf("Zahl = %d\n",tmp->zahl); - printf("Buchstabe = %c\n", tmp->buchstabe); - printf("Remaining = %x\n", *((uint64_t *)(ptr+sizeof(struct test)))); - */ - - KiroTrb *rb = g_object_new(KIRO_TYPE_TRB, NULL); - kiro_trb_reshape(rb, sizeof(uint64_t), 3); - void *buffer = kiro_trb_get_raw_buffer(rb); - uint64_t foo = 0xAFFED00F; - uint64_t bar = 0x1337BEEF; - memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); - memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); - memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); - kiro_trb_push(rb, &bar); - kiro_trb_push(rb, &foo); - kiro_trb_push(rb, &foo); - uint64_t *maman = kiro_trb_get_element(rb, 3); - printf("Stored in old: %x\n", *maman); - KiroTrb *rb2 = g_object_new(KIRO_TYPE_TRB, NULL); - kiro_trb_clone(rb2, kiro_trb_get_raw_buffer(rb)); - maman = kiro_trb_get_element(rb2, 3); - printf("Stored in New: %x\n", *maman); - sleep(1); - g_object_unref(rb); - g_object_unref(rb2); - - return 0; -} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..849d0b3 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${KIRO_SOURCE_DIR}/src) +link_directories(${KIRO_BINARY_DIR}/src) + +add_executable(client test-client.c) +target_link_libraries(client kiro SDL m gobject-2.0 glib-2.0) + +add_executable(server test-server.c) +target_link_libraries(server kiro gobject-2.0 glib-2.0) diff --git a/test/test-client.c b/test/test-client.c new file mode 100644 index 0000000..469aa5e --- /dev/null +++ b/test/test-client.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include "kiro-client.h" +#include "kiro-trb.h" +#include +#include + + +static _Bool init_app(const char * name, SDL_Surface * icon, uint32_t flags) +{ + atexit(SDL_Quit); + if(SDL_Init(flags) < 0) + return 0; + + SDL_WM_SetCaption(name, name); + SDL_WM_SetIcon(icon, NULL); + + return 1; +} + +static void render(SDL_Surface * sf) +{ + SDL_Surface * screen = SDL_GetVideoSurface(); + if(SDL_BlitSurface(sf, NULL, screen, NULL) == 0) + SDL_UpdateRect(screen, 0, 0, 0, 0); +} + +static int filter(const SDL_Event * event) +{ return event->type == SDL_QUIT; } + + +int main ( int argc, char *argv[] ) +{ + if (argc < 3) + { + printf("Not enough aruments. Usage: ./client
\n"); + return -1; + } + KiroClient *client = g_object_new(KIRO_TYPE_CLIENT, NULL); + if(-1 == kiro_client_connect(client, argv[1], argv[2])) + { + g_object_unref(client); + return -1; + } + + kiro_client_sync(client); + KiroTrb *trb = g_object_new(KIRO_TYPE_TRB, NULL); + kiro_trb_adopt(trb, kiro_client_get_memory(client)); + + _Bool ok = + init_app("UCA Images", NULL, SDL_INIT_VIDEO) && + SDL_SetVideoMode(512, 512, 8, SDL_HWSURFACE); + + assert(ok); + + uint32_t mask = 0xffffffff; + SDL_Surface * data_sf = SDL_CreateRGBSurfaceFrom( + kiro_trb_get_element(trb, 0), 512, 512, 8, 512, + mask, mask, mask, 0); + + SDL_Color colors[256]; + for(int i=0;i<256;i++){ + colors[i].r=i; + colors[i].g=i; + colors[i].b=i; + } + SDL_SetPalette(data_sf, SDL_LOGPAL|SDL_PHYSPAL, colors, 0, 256); + + SDL_SetEventFilter(filter); + + int cont = 1; + + //struct KiroTrbInfo *header = (struct KiroTrbInfo *)kiro_trb_get_raw_buffer(trb); + + while(cont) + { + for(SDL_Event event; SDL_PollEvent(&event);) + if(event.type == SDL_QUIT) cont=0; + + kiro_client_sync(client); + SDL_Delay(10); + render(data_sf); + } + + + g_object_unref(client); + return 0; +} + + + + + + + + diff --git a/test/test-server.c b/test/test-server.c new file mode 100644 index 0000000..63fefaa --- /dev/null +++ b/test/test-server.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include "kiro-server.h" +#include "kiro-trb.h" +#include +#include +#include +#include + + + +static const char g_digits[10][20] = { + /* 0 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 1 */ + { 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00 }, + /* 2 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + /* 3 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 4 */ + { 0xff, 0x00, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff }, + /* 5 */ + { 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 }, + /* 6 */ + { 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 7 */ + { 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00 }, + /* 8 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 9 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 } +}; + +static const guint DIGIT_WIDTH = 4; +static const guint DIGIT_HEIGHT = 5; + +static void +print_number (gchar *buffer, guint number, guint x, guint y, guint width) +{ + for (int i = 0; i < DIGIT_WIDTH; i++) { + for (int j = 0; j < DIGIT_HEIGHT; j++) { + char val = (char) g_digits[number][j*DIGIT_WIDTH+i]; + if(val != 0x00) { + //This should make the frame counter appear in a bright yellow + val = 0xBE; + } + buffer[(y+j)*width + (x+i)] = (guint8) val; + } + } +} + +static void +print_current_frame (gchar *buffer, guint number, guint width, guint height, GRand *rand) +{ + guint divisor = 10000000; + int x = 1; + + while (divisor > 0) { + print_number(buffer, number / divisor, x, 1, width); + number = number % divisor; + divisor = divisor / 10; + x += DIGIT_WIDTH + 1; + } + + + //Rainbow pattern is the same for every row. Just calculate one single + //Scanline, so we can reuse it and dont have to do the whole calculation + //for every row again. + char default_line[width]; + for (int p = 0; p < width; p++) { + default_line[p] = (char) ((p*256) / (width)); + } + + + //Use memcpy to quickly fill every row with the precalculated rainbow + //pattern + for (guint y = 16; y < height; y++) { + guint index = y * width; + memcpy(buffer+index, &default_line[0], width); + } + + //This block will fill a square at the center of the image with normal + //distributed random data + const double mean = 128.0; + const double std = 32.0; + + for (guint y = (height/3); y < ((height*2)/3); y++) { + guint row_start = y * width; + for (guint i = (width/3); i < ((width*2)/3); i++) { + int index = row_start + i; + double u1 = g_rand_double(rand); + double u2 = g_rand_double(rand); + double r = sqrt(-2 * log(u1)) * cos(2 * G_PI * u2); + buffer[index] = (guint8) (r * std + mean); + } + } +} + + +int main(void) +{ + KiroServer *server = g_object_new(KIRO_TYPE_SERVER, NULL); + KiroTrb *rb = g_object_new(KIRO_TYPE_TRB, NULL); + kiro_trb_reshape(rb, 512*512, 15); + GRand *rand = g_rand_new(); + if(0 > kiro_server_start(server, NULL, "60010", kiro_trb_get_raw_buffer(rb), kiro_trb_get_raw_size(rb))) + { + printf("Failed to start server properly.\n"); + goto done; + } + + guint frame = 0; + gchar *buffer = NULL; + while(1) + { + buffer = kiro_trb_dma_push(rb); + print_current_frame(buffer, frame, 512, 512, rand); + frame++; + } + +done: + g_rand_free(rand); + g_object_unref(rb); + + return 0; +} \ No newline at end of file diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..4aac2f5 --- /dev/null +++ b/test/test.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "kiro-trb.h" + +struct test { + uint32_t zahl; + uint8_t buchstabe; +} __attribute__((packed)); + + +int main(void) +{ + /* + void* ptr = malloc(sizeof(struct test) + sizeof(uint64_t)); + memset(ptr, 0xFA, sizeof(struct test) + sizeof(uint64_t)); + struct test foo; + foo.zahl = 42; + foo.buchstabe = 'R'; + memcpy(ptr, &foo, sizeof(foo)); + + struct test *tmp = (struct test *)ptr; + printf("Zahl = %d\n",tmp->zahl); + printf("Buchstabe = %c\n", tmp->buchstabe); + printf("Remaining = %x\n", *((uint64_t *)(ptr+sizeof(struct test)))); + */ + + KiroTrb *rb = g_object_new(KIRO_TYPE_TRB, NULL); + kiro_trb_reshape(rb, sizeof(uint64_t), 3); + void *buffer = kiro_trb_get_raw_buffer(rb); + uint64_t foo = 0xAFFED00F; + uint64_t bar = 0x1337BEEF; + memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); + memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); + memcpy(kiro_trb_dma_push(rb), &foo, sizeof(foo)); + kiro_trb_push(rb, &bar); + kiro_trb_push(rb, &foo); + kiro_trb_push(rb, &foo); + uint64_t *maman = kiro_trb_get_element(rb, 3); + printf("Stored in old: %x\n", *maman); + KiroTrb *rb2 = g_object_new(KIRO_TYPE_TRB, NULL); + kiro_trb_clone(rb2, kiro_trb_get_raw_buffer(rb)); + maman = kiro_trb_get_element(rb2, 3); + printf("Stored in New: %x\n", *maman); + sleep(1); + g_object_unref(rb); + g_object_unref(rb2); + + return 0; +} \ No newline at end of file -- cgit v1.2.3