Add adapter for LD_PRELOAD, TBC.

This commit is contained in:
fengbojiang 2023-04-06 15:02:39 +08:00
parent c0cab32e5f
commit 865ab0ed63
12 changed files with 2889 additions and 0 deletions

75
adapter/Makefile Normal file
View File

@ -0,0 +1,75 @@
TOPDIR=..
ifeq ($(FF_PATH),)
FF_PATH=${TOPDIR}
endif
ifneq ($(shell pkg-config --exists libdpdk && echo 0),0)
$(error "No installation of DPDK found, maybe you should export environment variable `PKG_CONFIG_PATH`")
endif
DEBUG=-O0 -gdwarf-2 -g3 -DDEBUG
PKGCONF ?= pkg-config
ifndef DEBUG
CFLAGS+= -g -O2
else
CFLAGS+= ${DEBUG}
endif
CFLAGS += -fPIC -Wall -Werror $(shell $(PKGCONF) --cflags libdpdk)
INCLUDES= -I. -I${FF_PATH}/lib
FF_LIBS= -L${FF_PATH}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
DPDK_LIBS+= $(shell $(PKGCONF) --static --libs libdpdk)
DPDK_LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread -lnuma
#DPDK_CFLAGS= -Wall -Werror -include ${FF_DPDK}/include/rte_config.h
#DPDK_CFLAGS+= -march=native -DRTE_MACHINE_CPUFLAG_SSE -DRTE_MACHINE_CPUFLAG_SSE2 -DRTE_MACHINE_CPUFLAG_SSE3
#DPDK_CFLAGS+= -DRTE_MACHINE_CPUFLAG_SSSE3 -DRTE_MACHINE_CPUFLAG_SSE4_1 -DRTE_MACHINE_CPUFLAG_SSE4_2
#DPDK_CFLAGS+= -DRTE_COMPILE_TIME_CPUFLAGS=RTE_CPUFLAG_SSE,RTE_CPUFLAG_SSE2,RTE_CPUFLAG_SSE3,RTE_CPUFLAG_SSSE3,RTE_CPUFLAG_SSE4_1,RTE_CPUFLAG_SSE4_2
#DPDK_CFLAGS+= -I${FF_DPDK}/include
CFLAGS+= ${INCLUDES} ${DPDK_CFLAGS}
FSTACK_LIBS= ${FF_LIBS} ${DPDK_LIBS}
FF_SYSCALL_LIBS=
FSTACK_SRCS= \
fstack.c \
ff_so_zone.c \
ff_socket_ops.c
FF_SYSCALL_SRCS= \
ff_so_zone.c \
ff_hook_syscall.c \
ff_linux_syscall.c
FSTACK_OBJS= $(patsubst %.c,%.o,${FSTACK_SRCS})
FF_SYSCALL_OBJS= $(patsubst %.c,%.o,${FF_SYSCALL_SRCS})
#TARGET= fstack libff_syscall.a
TARGET= fstack libff_syscall.so
all: ${TARGET}
fstack: ${FSTACK_OBJS}
cc -o $@ $^ ${FSTACK_LIBS}
#libff_syscall.a: ${FF_SYSCALL_OBJS}
libff_syscall.so: ${FF_SYSCALL_OBJS}
#ar -rcs $@ $^ ${FF_SYSCALL_LIBS}
${CC} -fPIC -shared -o $@ $^ ${FF_SYSCALL_LIBS}
${FSTACK_OBJS}: %.o: %.c
${CC} -c $(CFLAGS) ${PROF} $<
${FF_SYSCALL_OBJS}: %.o: %.c
${CC} -c $(CFLAGS) ${PROF} $<
.PHONY: clean
clean:
rm -f *.o ${TARGET}

21
adapter/ff_adapter.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _FF_ADAPTER_H
#define _FF_ADAPTER_H
/* socket.h */
//#define SOCK_CLOEXEC 0x10000000
//#define SOCK_NONBLOCK 0x20000000
#define SOCK_FSTACK 0x01000000
#define SOCK_KERNEL 0x02000000
int ff_adapter_init();
//int __attribute__((constructor)) ff_adapter_init(int argc, char * const argv[]);
/*-
* Verify whether the socket is supported by fstack or not.
*/
int fstack_territory(int domain, int type, int protocol);
/* Tell whether a 'sockfd' belongs to fstack. */
int is_fstack_fd(int fd);
#endif

View File

@ -0,0 +1,31 @@
FF_SYSCALL_DECL(int, socket, (int, int, int));
FF_SYSCALL_DECL(int, bind, (int, const struct sockaddr *, socklen_t));
FF_SYSCALL_DECL(int, listen, (int, int));
FF_SYSCALL_DECL(int, shutdown, (int, int));
FF_SYSCALL_DECL(int, getsockname, (int, struct sockaddr *, socklen_t *));
FF_SYSCALL_DECL(int, getpeername, (int, struct sockaddr *, socklen_t *));
FF_SYSCALL_DECL(int, getsockopt, (int, int, int, void *, socklen_t *));
FF_SYSCALL_DECL(int, setsockopt, (int, int, int, const void *, socklen_t));
FF_SYSCALL_DECL(int, accept, (int, struct sockaddr *, socklen_t *));
FF_SYSCALL_DECL(int, accept4,(int, struct sockaddr *, socklen_t *, int flags));
FF_SYSCALL_DECL(int, connect, (int, const struct sockaddr *, socklen_t));
FF_SYSCALL_DECL(ssize_t, recv, (int, void *, size_t, int));
FF_SYSCALL_DECL(ssize_t, send, (int, const void *, size_t, int));
FF_SYSCALL_DECL(ssize_t, read, (int, void *, size_t));
FF_SYSCALL_DECL(ssize_t, write, (int, const void *, size_t));
FF_SYSCALL_DECL(ssize_t, writev, (int, const struct iovec *, int));
FF_SYSCALL_DECL(ssize_t, readv, (int, const struct iovec *, int));
FF_SYSCALL_DECL(ssize_t, sendto, (int, const void *, size_t, int,
const struct sockaddr *, socklen_t));
FF_SYSCALL_DECL(ssize_t, recvfrom, (int, void *, size_t, int,
struct sockaddr *, socklen_t *));
FF_SYSCALL_DECL(ssize_t, sendmsg, (int, const struct msghdr *, int flags));
FF_SYSCALL_DECL(ssize_t, recvmsg, (int, struct msghdr *, int flags));
FF_SYSCALL_DECL(int, close, (int));
FF_SYSCALL_DECL(int, ioctl, (int, unsigned long, unsigned long));
FF_SYSCALL_DECL(int, fcntl, (int, int, unsigned long));
FF_SYSCALL_DECL(int, epoll_create, (int));
FF_SYSCALL_DECL(int, epoll_ctl, (int, int, int, struct epoll_event *));
FF_SYSCALL_DECL(int, epoll_wait, (int, struct epoll_event *, int, int));
FF_SYSCALL_DECL(pid_t, fork, (void));
#undef FF_SYSCALL_DECL

1538
adapter/ff_hook_syscall.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#ifndef _FF_HOOK_SYSCALL_H
#define _FF_HOOK_SYSCALL_H
#undef FF_SYSCALL_DECL
#define FF_SYSCALL_DECL(ret, fn, args) extern ret ff_hook_##fn args
#include <ff_declare_syscalls.h>
#endif

236
adapter/ff_linux_syscall.c Normal file
View File

@ -0,0 +1,236 @@
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <dlfcn.h>
#include "ff_socket_ops.h"
#include "ff_linux_syscall.h"
#define SYSCALL(symbol, para) { \
if (linux_syscall_inited == 0) { \
if (linux_syscall_init() != 0) { \
return -1; \
} \
} \
if (syscalls.pf_##symbol) { \
return syscalls.pf_##symbol para; \
} \
errno = ENOSYS; \
return -1; \
}
struct ff_linux_syscall {
#define FF_SYSCALL_DECL(ret, fn, args) ret (*pf_##fn) args;
#include "ff_declare_syscalls.h"
};
static int linux_syscall_inited;
static struct ff_linux_syscall syscalls = { 0 };
static void *linux_lib_handle = NULL;
pthread_mutex_t syscall_init_mutex = PTHREAD_MUTEX_INITIALIZER;
static inline int
linux_syscall_load_symbol()
{
linux_lib_handle = dlopen ("libc.so.6", RTLD_NOW | RTLD_GLOBAL);
if (linux_lib_handle == NULL) {
ERR_LOG("cannot dlopen libc.so.6] err_string=%s", dlerror());
return -1;
}
#define FF_SYSCALL_DECL(ret, fn, args) \
syscalls.pf_##fn = (typeof(syscalls.pf_##fn))dlsym(linux_lib_handle, #fn);
#include <ff_declare_syscalls.h>
return 0;
}
static inline int
linux_syscall_init()
{
if (linux_syscall_inited) {
return 0;
}
pthread_mutex_lock(&syscall_init_mutex);
if (linux_syscall_inited) {
pthread_mutex_unlock(&syscall_init_mutex);
return 0;
}
if (linux_syscall_load_symbol() != 0) {
pthread_mutex_unlock(&syscall_init_mutex);
return -1;
}
linux_syscall_inited = 1;
pthread_mutex_unlock(&syscall_init_mutex);
return 0;
}
int
ff_linux_socket(int domain, int type, int protocol)
{
DEBUG_LOG("ff_linux_socket, domain:%d, type:%d, protocol:%d\n", domain, type, protocol);
SYSCALL(socket, (domain, type, protocol));
}
int
ff_linux_bind(int s, const struct sockaddr *addr,
socklen_t addrlen)
{
SYSCALL(bind, (s, addr, addrlen));
}
int
ff_linux_listen(int s, int backlog)
{
SYSCALL(listen, (s, backlog));
}
int ff_linux_shutdown(int s, int how)
{
SYSCALL(shutdown, (s, how));
}
int ff_linux_getsockname(int s, struct sockaddr *name,
socklen_t *namelen)
{
SYSCALL(getsockname, (s, name, namelen));
}
int ff_linux_getpeername(int s, struct sockaddr *name,
socklen_t *namelen)
{
SYSCALL(getpeername, (s, name, namelen));
}
int ff_linux_getsockopt(int s, int level, int optname,
void *optval, socklen_t *optlen)
{
SYSCALL(getsockopt, (s, level, optname, optval, optlen));
}
int ff_linux_setsockopt(int s, int level, int optname,
const void *optval, socklen_t optlen)
{
SYSCALL(setsockopt, (s, level, optname, optval, optlen));
}
int ff_linux_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
SYSCALL(accept, (s, addr, addrlen));
}
int ff_linux_accept4(int s, struct sockaddr *addr,
socklen_t *addrlen, int flags)
{
SYSCALL(accept4, (s, addr, addrlen, flags));
}
int ff_linux_connect(int s, const struct sockaddr *addr,
socklen_t addrlen)
{
SYSCALL(connect, (s, addr, addrlen));
}
ssize_t ff_linux_recv(int s, void *buf, size_t len, int flags)
{
SYSCALL(recv, (s, buf, len, flags));
}
ssize_t ff_linux_send(int s, const void *buf, size_t len, int flags)
{
SYSCALL(send, (s, buf, len, flags));
}
ssize_t ff_linux_read(int s, void *buf, size_t len)
{
SYSCALL(read, (s, buf, len));
}
ssize_t ff_linux_write(int s, const void *buf, size_t len)
{
SYSCALL(write, (s, buf, len));
}
ssize_t ff_linux_writev(int s, const struct iovec *iov, int iovcnt)
{
SYSCALL(writev, (s, iov, iovcnt));
}
ssize_t ff_linux_readv(int s, const struct iovec *iov, int iovcnt)
{
SYSCALL(readv, (s, iov, iovcnt));
}
ssize_t ff_linux_sendto(int s, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
SYSCALL(sendto, (s, buf, len, flags, to, tolen));
}
ssize_t ff_linux_recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
SYSCALL(recvfrom, (s, buf, len, flags, from, fromlen));
}
ssize_t ff_linux_sendmsg(int s, const struct msghdr *msg, int flags)
{
SYSCALL(sendmsg, (s, msg, flags));
}
ssize_t ff_linux_recvmsg(int s, struct msghdr *msg, int flags)
{
SYSCALL(recvmsg, (s, msg, flags))
}
int ff_linux_close(int s)
{
SYSCALL(close, (s));
}
int ff_linux_ioctl(int s, unsigned long req, unsigned long data)
{
SYSCALL(ioctl, (s, req, data));
}
int ff_linux_fcntl(int s, int cmd, unsigned long data)
{
SYSCALL(fcntl, (s, cmd, data));
}
int ff_linux_epoll_create(int size)
{
DEBUG_LOG("ff_linux_epoll_create, fdsize:%d\n", size);
SYSCALL(epoll_create, (size));
}
int ff_linux_epoll_ctl(int epfd, int op, int fd,
struct epoll_event *event)
{
DEBUG_LOG("ff_linux_epoll_ctl, epfd:%d, op:%d, fd:%d\n", epfd, op, fd);
SYSCALL(epoll_ctl, (epfd, op, fd, event));
}
int
ff_linux_epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout)
{
DEBUG_LOG("ff_linux_epoll_wait, epfd:%d, maxevents:%d, timeout:%d\n", epfd, maxevents, timeout);
SYSCALL(epoll_wait, (epfd, events, maxevents, timeout));
}
pid_t
ff_linux_fork(void)
{
SYSCALL(fork, ());
}

View File

@ -0,0 +1,13 @@
#ifndef _FF_LINUX_SYSCALL_H_
#define _FF_LINUX_SYSCALL_H_
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#undef FF_SYSCALL_DECL
#define FF_SYSCALL_DECL(ret, fn, args) ret ff_linux_##fn args
#include "ff_declare_syscalls.h"
#endif

170
adapter/ff_so_zone.c Normal file
View File

@ -0,0 +1,170 @@
#include <stdio.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_memzone.h>
#include "ff_config.h"
#include "ff_socket_ops.h"
#define SOCKET_OPS_ZONE_NAME "ff_socket_ops_zone_%d"
#define SOCKET_OPS_CONTEXT_MAX_NUM 32
#define SOCKET_OPS_CONTEXT_NAME_SIZE 32
#define SOCKET_OPS_CONTEXT_NAME "ff_so_context_"
static uint16_t ff_max_so_context = SOCKET_OPS_CONTEXT_MAX_NUM;
struct ff_socket_ops_zone *ff_so_zone;
int
ff_set_max_so_context(uint16_t count)
{
if (ff_so_zone) {
ERR_LOG("Can not set: memzone has inited\n");
return -1;
}
/*if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
ERR_LOG("Can not set: process is not primary\n");
return 1;
}*/
ff_max_so_context = count;
return 0;
}
int
ff_create_so_memzone()
{
if (ff_so_zone) {
ERR_LOG("Can not create memzone: memzone has inited\n");
return -1;
}
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
uint16_t i, proc_id;
for (proc_id = 0; proc_id < ff_global_cfg.dpdk.nb_procs; proc_id++) {
struct ff_socket_ops_zone *so_zone_tmp;
const struct rte_memzone *mz;
char zn[64];
size_t zone_size = sizeof(struct ff_socket_ops_zone) +
sizeof(struct ff_so_context) * ff_max_so_context;
snprintf(zn, sizeof(zn), SOCKET_OPS_ZONE_NAME, proc_id);
ERR_LOG("To create memzone:%s\n", zn);
mz = rte_memzone_reserve(zn, zone_size, rte_socket_id(), 0);
if (mz == NULL) {
ERR_LOG("Cannot reserve memory zone:%s\n", zn);
return -1;
}
memset(mz->addr, 0, zone_size);
so_zone_tmp = mz->addr;
rte_spinlock_init(&so_zone_tmp->lock);
so_zone_tmp->count = ff_max_so_context;
so_zone_tmp->free = so_zone_tmp->count;
so_zone_tmp->sc = (struct ff_so_context *)(so_zone_tmp + 1);
for (i = 0; i < ff_max_so_context; i++) {
struct ff_so_context *sc = &so_zone_tmp->sc[i];
rte_spinlock_init(&sc->lock);
sc->status = FF_SC_IDLE;
sc->inuse = 0;
if (sem_init(&sc->wait_sem, 1, 0) == -1) {
ERR_LOG("Initialize semaphore failed:%d\n", errno);
return -1;
}
}
if (proc_id == 0) {
ff_so_zone = so_zone_tmp;
}
}
}else {
const struct rte_memzone *mz;
char zn[64];
snprintf(zn, sizeof(zn), SOCKET_OPS_ZONE_NAME, ff_global_cfg.dpdk.proc_id);
ERR_LOG("To lookup memzone:%s\n", zn);
mz = rte_memzone_lookup(zn);
if (mz == NULL) {
ERR_LOG("Lookup memory zone:%s failed\n", zn);
return -1;
}
ff_so_zone = mz->addr;
}
return 0;
}
struct ff_so_context *
ff_attach_so_context(int proc_id)
{
struct ff_so_context *sc = NULL;
uint16_t i;
if (ff_so_zone == NULL) {
const struct rte_memzone *mz;
char zn[64];
snprintf(zn, sizeof(zn), SOCKET_OPS_ZONE_NAME, proc_id);
ERR_LOG("To lookup memzone:%s\n", zn);
mz = rte_memzone_lookup(zn);
if (mz == NULL) {
ERR_LOG("Lookup memory zone:%s failed\n", zn);
return NULL;
}
ff_so_zone = mz->addr;
}
rte_spinlock_lock(&ff_so_zone->lock);
if (ff_so_zone->free == 0) {
ERR_LOG("Attach memzone failed: no free context\n");
rte_spinlock_unlock(&ff_so_zone->lock);
return NULL;
}
/* i从count-free开始尝试直到一轮结束 */
for (i = 0; i < ff_so_zone->count; i++) {
sc = &ff_so_zone->sc[i];
if (sc->inuse == 0) {
sc->inuse = 1;
rte_spinlock_init(&sc->lock);
sc->status = FF_SC_IDLE;
ff_so_zone->free--;
break;
}
}
DEBUG_LOG("attach sc:%p, i:%d\n", sc, i);
rte_spinlock_unlock(&ff_so_zone->lock);
return sc;
}
void
ff_detach_so_context(struct ff_so_context *sc)
{
if (ff_so_zone == NULL || sc == NULL) {
return;
}
rte_spinlock_lock(&ff_so_zone->lock);
sc->inuse = 0;
ff_so_zone->free++;
DEBUG_LOG("detach sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
rte_spinlock_unlock(&ff_so_zone->lock);
}

461
adapter/ff_socket_ops.c Normal file
View File

@ -0,0 +1,461 @@
#include <rte_memcpy.h>
#include <rte_spinlock.h>
#include "ff_socket_ops.h"
#include "ff_sysproto.h"
#include "ff_api.h"
#include "ff_epoll.h"
#undef FF_SYSCALL_DECL
#define FF_SYSCALL_DECL(ret, fn, none) \
static ret ff_sys_##fn(struct ff_##fn##_args *args);
#include <ff_declare_syscalls.h>
static int ff_sys_kqueue(struct ff_kqueue_args *args);
static int ff_sys_kevent(struct ff_kevent_args *args);
extern struct ff_socket_ops_zone *ff_so_zone;
#define FF_MAX_BOUND_NUM 8
struct ff_bound_info {
int fd;
struct sockaddr addr;
};
static struct ff_bound_info ff_bound_fds[FF_MAX_BOUND_NUM];
static int
sockaddr_cmp(struct sockaddr *a, struct sockaddr *b)
{
struct sockaddr_in *sina, *sinb;
sina = (struct sockaddr_in *)a;
sinb = (struct sockaddr_in *)b;
if (sina->sin_family != sinb->sin_family) {
return 1;
}
if (sina->sin_port != sinb->sin_port) {
return 1;
}
if (sina->sin_addr.s_addr != sinb->sin_addr.s_addr) {
return 1;
}
return 0;
}
static int
sockaddr_is_bound(struct sockaddr *addr)
{
int i;
for (i = 0; i < FF_MAX_BOUND_NUM; i++) {
struct ff_bound_info *info = &ff_bound_fds[i];
if (info->fd == 0) {
continue;
}
if (sockaddr_cmp(&info->addr, addr) == 0) {
return info->fd;
}
}
return 0;
}
static int
sockaddr_bind(int fd, struct sockaddr *addr)
{
int i;
for (i = 0; i < FF_MAX_BOUND_NUM; i++) {
struct ff_bound_info *info = &ff_bound_fds[i];
if (info->fd != 0) {
continue;
}
info->fd = fd;
rte_memcpy(&info->addr, addr, sizeof(struct sockaddr));
return 0;
}
return -1;
}
static int
sockaddr_unbind(int fd)
{
int i;
for (i = 0; i < FF_MAX_BOUND_NUM; i++) {
struct ff_bound_info *info = &ff_bound_fds[i];
if (info->fd != fd) {
continue;
}
info->fd = 0;
return 0;
}
return -1;
}
static int
ff_sys_socket(struct ff_socket_args *args)
{
return ff_socket(args->domain, args->type, args->protocol);
}
static int
ff_sys_bind(struct ff_bind_args *args)
{
int bound_fd;
int ret;
bound_fd = sockaddr_is_bound(args->addr);
if (bound_fd != 0 && bound_fd != args->fd) {
return ff_dup2(bound_fd, args->fd);
}
ret = ff_bind(args->fd, args->addr, args->addrlen);
if (ret == 0) {
sockaddr_bind(args->fd, args->addr);
}
return ret;
}
static int
ff_sys_listen(struct ff_listen_args *args)
{
return ff_listen(args->fd, args->backlog);
}
static int
ff_sys_shutdown(struct ff_shutdown_args *args)
{
return ff_shutdown(args->fd, args->how);
}
static int
ff_sys_getsockname(struct ff_getsockname_args *args)
{
return ff_getsockname(args->fd, args->name, args->namelen);
}
static int
ff_sys_getpeername(struct ff_getpeername_args *args)
{
return ff_getpeername(args->fd, args->name, args->namelen);
}
static int
ff_sys_getsockopt(struct ff_getsockopt_args *args)
{
return ff_getsockopt(args->fd, args->level, args->name,
args->optval, args->optlen);
}
static int
ff_sys_setsockopt(struct ff_setsockopt_args *args)
{
return ff_setsockopt(args->fd, args->level, args->name,
args->optval, args->optlen);
}
static int
ff_sys_accept(struct ff_accept_args *args)
{
return ff_accept(args->fd, args->addr, args->addrlen);
}
static int
ff_sys_accept4(struct ff_accept4_args *args)
{
errno = ENOSYS;
return -1;
}
static int
ff_sys_connect(struct ff_connect_args *args)
{
return ff_connect(args->fd, args->addr, args->addrlen);
}
static ssize_t
ff_sys_recv(struct ff_recv_args *args)
{
return ff_recv(args->fd, args->buf, args->len, args->flags);
}
static ssize_t
ff_sys_recvfrom(struct ff_recvfrom_args *args)
{
return ff_recvfrom(args->fd, args->buf, args->len, args->flags,
args->from, args->fromlen);
}
static ssize_t
ff_sys_recvmsg(struct ff_recvmsg_args *args)
{
return ff_recvmsg(args->fd, args->msg, args->flags);
}
static ssize_t
ff_sys_read(struct ff_read_args *args)
{
return ff_read(args->fd, args->buf, args->len);
}
static ssize_t
ff_sys_readv(struct ff_readv_args *args)
{
return ff_readv(args->fd, args->iov, args->iovcnt);
}
static ssize_t
ff_sys_send(struct ff_send_args *args)
{
return ff_send(args->fd, args->buf, args->len, args->flags);
}
static ssize_t
ff_sys_sendto(struct ff_sendto_args *args)
{
return ff_sendto(args->fd, args->buf, args->len, args->flags,
args->to, args->tolen);
}
static ssize_t
ff_sys_sendmsg(struct ff_sendmsg_args *args)
{
return ff_sendmsg(args->fd, args->msg, args->flags);
}
static ssize_t
ff_sys_write(struct ff_write_args *args)
{
return ff_write(args->fd, args->buf, args->len);
}
static ssize_t
ff_sys_writev(struct ff_writev_args *args)
{
return ff_writev(args->fd, args->iov, args->iovcnt);
}
static int
ff_sys_close(struct ff_close_args *args)
{
sockaddr_unbind(args->fd);
return ff_close(args->fd);
}
static int
ff_sys_ioctl(struct ff_ioctl_args *args)
{
return ff_ioctl(args->fd, args->com, args->data);
}
static int
ff_sys_fcntl(struct ff_fcntl_args *args)
{
return ff_fcntl(args->fd, args->cmd, args->data);
}
static int
ff_sys_epoll_create(struct ff_epoll_create_args *args)
{
DEBUG_LOG("to run ff_epoll_create, size:%d\n", args->size);
return ff_epoll_create(args->size);
}
static int
ff_sys_epoll_ctl(struct ff_epoll_ctl_args *args)
{
DEBUG_LOG("to run ff_epoll_ctl, epfd:%d, op:%d, fd:%d\n",
args->epfd, args->op, args->fd);
return ff_epoll_ctl(args->epfd, args->op, args->fd,
args->event);
}
static int
ff_sys_epoll_wait(struct ff_epoll_wait_args *args)
{
DEBUG_LOG("to run ff_epoll_wait, epfd:%d, maxevents:%d, timeout:%d\n",
args->epfd, args->maxevents, args->timeout);
return ff_epoll_wait(args->epfd, args->events,
args->maxevents, args->timeout);
}
static int
ff_sys_kqueue(struct ff_kqueue_args *args)
{
return ff_kqueue();
}
static int
ff_sys_kevent(struct ff_kevent_args *args)
{
return ff_kevent(args->kq, args->changelist, args->nchanges,
args->eventlist, args->nevents, args->timeout);
}
static pid_t
ff_sys_fork(struct ff_fork_args *args)
{
errno = ENOSYS;
return -1;
}
static int
ff_so_handler(int ops, void *args)
{
DEBUG_LOG("ff_so_handler ops:%d, epoll create ops:%d\n", ops, FF_SO_EPOLL_CREATE);
switch(ops) {
case FF_SO_SOCKET:
return ff_sys_socket((struct ff_socket_args *)args);
case FF_SO_BIND:
return ff_sys_bind((struct ff_bind_args *)args);
case FF_SO_LISTEN:
return ff_sys_listen((struct ff_listen_args *)args);
case FF_SO_CONNECT:
return ff_sys_connect((struct ff_connect_args *)args);
case FF_SO_SHUTDOWN:
return ff_sys_shutdown((struct ff_shutdown_args *)args);
case FF_SO_GETSOCKNAME:
return ff_sys_getsockname((struct ff_getsockname_args *)args);
case FF_SO_GETPEERNAME:
return ff_sys_getpeername((struct ff_getpeername_args *)args);
case FF_SO_GETSOCKOPT:
return ff_sys_getsockopt((struct ff_getsockopt_args *)args);
case FF_SO_SETSOCKOPT:
return ff_sys_setsockopt((struct ff_setsockopt_args *)args);
case FF_SO_ACCEPT:
return ff_sys_accept((struct ff_accept_args *)args);
case FF_SO_ACCEPT4:
return ff_sys_accept4((struct ff_accept4_args *)args);
case FF_SO_RECV:
return ff_sys_recv((struct ff_recv_args *)args);
case FF_SO_RECVFROM:
return ff_sys_recvfrom((struct ff_recvfrom_args *)args);
case FF_SO_RECVMSG:
return ff_sys_recvmsg((struct ff_recvmsg_args *)args);
case FF_SO_READ:
return ff_sys_read((struct ff_read_args *)args);
case FF_SO_READV:
return ff_sys_readv((struct ff_readv_args *)args);
case FF_SO_SEND:
return ff_sys_send((struct ff_send_args *)args);
case FF_SO_SENDTO:
return ff_sys_sendto((struct ff_sendto_args *)args);
case FF_SO_SENDMSG:
return ff_sys_sendmsg((struct ff_sendmsg_args *)args);
case FF_SO_WRITE:
return ff_sys_write((struct ff_write_args *)args);
case FF_SO_WRITEV:
return ff_sys_writev((struct ff_writev_args *)args);
case FF_SO_CLOSE:
return ff_sys_close((struct ff_close_args *)args);
case FF_SO_IOCTL:
return ff_sys_ioctl((struct ff_ioctl_args *)args);
case FF_SO_FCNTL:
return ff_sys_fcntl((struct ff_fcntl_args *)args);
case FF_SO_EPOLL_CREATE:
return ff_sys_epoll_create((struct ff_epoll_create_args *)args);
case FF_SO_EPOLL_CTL:
return ff_sys_epoll_ctl((struct ff_epoll_ctl_args *)args);
case FF_SO_EPOLL_WAIT:
return ff_sys_epoll_wait((struct ff_epoll_wait_args *)args);
case FF_SO_KQUEUE:
return ff_sys_kqueue((struct ff_kqueue_args *)args);
case FF_SO_KEVENT:
return ff_sys_kevent((struct ff_kevent_args *)args);
case FF_SO_FORK:
return ff_sys_fork((struct ff_fork_args *)args);
default:
break;
}
errno = EINVAL;
return (-1);
}
static void
ff_handle_kevent(struct ff_so_context *sc)
{
struct ff_kevent_args *ka = sc->args;
errno = 0;
sc->result = ff_sys_kevent(ka);
sc->error = errno;
if (ka->nchanges) {
ka->nchanges = 0;
}
if (sc->result == 0 && ka->nevents != 0) {
return;
}
sc->status = FF_SC_REP;
sem_post(&sc->wait_sem);
}
static inline void
ff_handle_socket_ops(struct ff_so_context *sc)
{
if (sc->inuse == 0) {
return;
}
if (!rte_spinlock_trylock(&sc->lock)) {
return;
}
if (sc->status != FF_SC_REQ) {
rte_spinlock_unlock(&sc->lock);
return;
}
DEBUG_LOG("ff_handle_socket_ops sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
if (sc->ops == FF_SO_KEVENT) {
ff_handle_kevent(sc);
rte_spinlock_unlock(&sc->lock);
return;
}
errno = 0;
sc->result = ff_so_handler(sc->ops, sc->args);
sc->error = errno;
sc->status = FF_SC_REP;
if (sc->ops == FF_SO_EPOLL_WAIT) {
sem_post(&sc->wait_sem);
}
rte_spinlock_unlock(&sc->lock);
}
void
ff_handle_each_context()
{
uint16_t i;
rte_spinlock_lock(&ff_so_zone->lock);
for (i = 0; i < ff_so_zone->count; i++) {
struct ff_so_context *sc = &ff_so_zone->sc[i];
ff_handle_socket_ops(sc);
}
rte_spinlock_unlock(&ff_so_zone->lock);
}

103
adapter/ff_socket_ops.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef _FF_SOCKET_OPS_H_
#define _FF_SOCKET_OPS_H_
#include <semaphore.h>
#include <rte_atomic.h>
#include <rte_spinlock.h>
#define ERR_LOG(fmt, ...) do { \
printf("file:%s, line:%u, fun:%s, "fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
} while (0)
#ifdef DEBUG
#define DEBUG_LOG ERR_LOG
#else
#define DEBUG_LOG(...)
#endif
enum FF_SOCKET_OPS {
FF_SO_SOCKET,
FF_SO_LISTEN,
FF_SO_BIND,
FF_SO_CONNECT,
FF_SO_SHUTDOWN,
FF_SO_GETSOCKNAME,
FF_SO_GETPEERNAME,
FF_SO_GETSOCKOPT,
FF_SO_SETSOCKOPT,
FF_SO_ACCEPT,
FF_SO_ACCEPT4,
FF_SO_RECV,
FF_SO_RECVFROM,
FF_SO_RECVMSG,
FF_SO_READ,
FF_SO_READV,
FF_SO_SEND,
FF_SO_SENDTO,
FF_SO_SENDMSG,
FF_SO_WRITE,
FF_SO_WRITEV,
FF_SO_CLOSE,
FF_SO_IOCTL,
FF_SO_FCNTL,
FF_SO_EPOLL_CREATE,
FF_SO_EPOLL_CTL,
FF_SO_EPOLL_WAIT,
FF_SO_KQUEUE,
FF_SO_KEVENT,
FF_SO_FORK,
};
enum FF_SO_CONTEXT_STATUS {
FF_SC_IDLE,
FF_SC_REQ,
FF_SC_REP,
};
struct ff_socket_ops_zone {
rte_spinlock_t lock;
/* total number of so_contex */
uint16_t count;
/* free number of so_context */
uint16_t free;
struct ff_so_context *sc;
} __attribute__((packed));
struct ff_so_context {
rte_spinlock_t lock;
int status;
sem_t wait_sem;
enum FF_SOCKET_OPS ops;
void *args;
/* result of ops processing */
ssize_t result;
/* errno if failed */
int error;
/* 1 if used, else 0 */
int inuse;
// listen fd, refcount..
} __attribute__((packed));
extern struct ff_socket_ops_zone *ff_so_zone;
/* For primary process */
int ff_set_max_so_context(uint16_t count);
int ff_create_so_memzone();
void ff_handle_each_context();
/* For secondary process */
struct ff_so_context *ff_attach_so_context(int proc_id);
void ff_detach_so_context(struct ff_so_context *context);
#endif

197
adapter/ff_sysproto.h Normal file
View File

@ -0,0 +1,197 @@
#ifndef _FF_SYSPROTO_H_
#define _FF_SYSPROTO_H_
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <time.h>
struct ff_socket_args {
int domain;
int type;
int protocol;
};
struct ff_bind_args {
int fd;
void *addr;
int addrlen;
};
struct ff_listen_args {
int fd;
int backlog;
};
struct ff_shutdown_args {
int fd;
int how;
};
struct ff_getpeername_args {
int fd;
void *name;
socklen_t *namelen;
};
struct ff_getsockname_args {
int fd;
void *name;
socklen_t *namelen;
};
struct ff_setsockopt_args {
int fd;
int level;
int name;
void *optval;
socklen_t optlen;
};
struct ff_getsockopt_args {
int fd;
int level;
int name;
void *optval;
socklen_t *optlen;
};
struct ff_accept_args {
int fd;
void *addr;
socklen_t *addrlen;
};
struct ff_accept4_args {
int fd;
void *addr;
socklen_t *addrlen;
int flags;
};
struct ff_connect_args {
int fd;
void *addr;
int addrlen;
};
struct ff_recv_args {
int fd;
void *buf;
size_t len;
int flags;
};
struct ff_recvfrom_args {
int fd;
void *buf;
size_t len;
int flags;
void *from;
socklen_t *fromlen;
};
struct ff_recvmsg_args {
int fd;
struct msghdr *msg;
int flags;
};
struct ff_read_args {
int fd;
void *buf;
size_t len;
};
struct ff_readv_args {
int fd;
struct iovec *iov;
int iovcnt;
};
struct ff_send_args {
int fd;
void *buf;
size_t len;
int flags;
};
struct ff_sendto_args {
int fd;
void *buf;
size_t len;
int flags;
void *to;
int tolen;
};
struct ff_sendmsg_args {
int fd;
struct msghdr * msg;
int flags;
};
struct ff_write_args {
int fd;
void *buf;
size_t len;
};
struct ff_writev_args {
int fd;
struct iovec *iov;
int iovcnt;
};
struct ff_close_args {
int fd;
};
struct ff_ioctl_args {
int fd;
unsigned long com;
void *data;
};
struct ff_fcntl_args {
int fd;
int cmd;
long data;
};
struct ff_epoll_create_args {
int size;
};
struct ff_epoll_ctl_args {
int epfd;
int op;
int fd;
struct epoll_event *event;
};
struct ff_epoll_wait_args {
int epfd;
struct epoll_event *events;
int maxevents;
int timeout;
};
struct ff_kqueue_args {
};
struct ff_kevent_args {
int kq;
struct kevent *changelist;
int nchanges;
struct kevent *eventlist;
int nevents;
struct timespec *timeout;
};
struct ff_fork_args {
};
#endif

36
adapter/fstack.c Normal file
View File

@ -0,0 +1,36 @@
#include "ff_api.h"
#include "ff_socket_ops.h"
#define WORKERS 32
int
loop(void *arg)
{
ff_handle_each_context();
return 0;
}
int
main(int argc, char * argv[])
{
int ret;
ff_init(argc, argv);
ret = ff_set_max_so_context(WORKERS);
if (ret < 0) {
return -1;
}
ret = ff_create_so_memzone();
if (ret < 0) {
return -1;
}
ERR_LOG("ff_create_so_memzone successful\n");
ff_run(loop, NULL);
return 0;
}