Merge branch 'preload_syscall' into dev

This commit is contained in:
fengbojiang 2023-05-03 23:25:53 +08:00
commit 419e3b16fe
61 changed files with 5263 additions and 1 deletions

13
adapter/README.md Normal file
View File

@ -0,0 +1,13 @@
This directory stores some adapters based on the F-Stack lib library, currently includes `micro_thread` and `syscall`.
## micro_thread
Provides micro thread interface. Various applications with stateful applications can easily use F-Stack to get high performance without processing complex asynchronous logic.
## syscall
Hijack Linux kernel syscall with f-stack api, can use `LD_PRELOAD` to support existing applications, such as Nginx.
It also can support f-stack and kernel stack at the same time.

25
adapter/syscall/LICENSE Normal file
View File

@ -0,0 +1,25 @@
This is BSD 2-Clause licensed.
Copyright (C) 2023 THL A29 Limited, a Tencent company.
All rights reserved.
Terms of the BSD 2-Clause License:
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

107
adapter/syscall/Makefile Normal file
View File

@ -0,0 +1,107 @@
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
# Per thread separate initialization dpdk lib and attach sc when needed,
# such as listen same port in different threads, and socket can use in own thread.
# Default disable.
#
# If disable it, one socket can use in all threads.
#FF_THREAD_SOCKET=1
# If enable FF_KERNEL_EVENT, epoll_create/epoll_clt/epoll_wait always call f-stack and system API at the same time.
# Use for some scenarios similar to Nginx.
#FF_KERNEL_EVENT=1
PKGCONF ?= pkg-config
ifndef DEBUG
CFLAGS+= -g -O2 -DNDEBUG
else
CFLAGS+= ${DEBUG}
endif
ifdef FF_THREAD_SOCKET
CFLAGS+= -DFF_THREAD_SOCKET
endif
ifdef FF_KERNEL_EVENT
CFLAGS+= -DFF_KERNEL_EVENT
endif
ifdef FF_MULTI_SC
CFLAGS+= -DFF_MULTI_SC
endif
CFLAGS += -fPIC -Wall -Werror $(shell $(PKGCONF) --cflags libdpdk)
INCLUDES= -I. -I${FF_PATH}/lib
LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread -lnuma
FF_LIBS= -L${FF_PATH}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive
DPDK_LIBS+= $(shell $(PKGCONF) --static --libs libdpdk)
DPDK_LIBS+= ${LIBS}
#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 example
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} ${DPDK_LIBS}
example:
cc ${CFLAGS} -I ${FF_PATH}/adapter/syscall -L ${FF_PATH}/adapter/syscall -lff_syscall -o helloworld_stack main_stack.c ${LIBS}
cc ${CFLAGS} -I ${FF_PATH}/adapter/syscall -L ${FF_PATH}/adapter/syscall -lff_syscall -o helloworld_stack_thread_socket main_stack_thread_socket.c ${LIBS}
cc ${CFLAGS} -I ${FF_PATH}/adapter/syscall -o helloworld_stack_epoll main_stack_epoll.c ${LIBS}
cc ${CFLAGS} -I ${FF_PATH}/adapter/syscall -o helloworld_stack_epoll_thread_socket main_stack_epoll_thread_socket.c ${LIBS}
cc ${CFLAGS} -I ${FF_PATH}/adapter/syscall -o helloworld_stack_epoll_kernel main_stack_epoll_kernel.c ${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}

View File

@ -0,0 +1,4 @@
# F-Stack LD_PRELOAD Beta Introduction
[To be translated](https://mp.weixin.qq.com/s?__biz=MzI5ODY3Nzc5OA==&tempkey=MTIxNl9Kd0pabEJ4em95c3J6OFJJdUYzZ2F2aGthLURKQmplYnJIVmE0cTFsSzNqdkhFM3JjV1F1SjlrMWFxeVo0Nks0b0lwOG5UbEZueVRTb0RFcnQ5LW42UE1aNVFUYW9mMHVaRjFiWXBKcG9VY0FYTTJIdUgxcU5UdTltb0hId0EtODBHR3lZM1FuX1FxdHNMQkJsWExTb3IyQ0MycDkxWXlBTllNOVlBfn4%3D&chksm=eca3623edbd4eb28e8d7dc68001f46381d39f4ffca91037a4ad8f8ed5b59bad2354ca273601b&token=39899456&lang=zh_CN#rd).

View File

@ -0,0 +1,23 @@
#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[]);
void alarm_event_sem();
/*-
* 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
#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>
extern int kqueue(void);
extern int kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout);
#endif

View File

@ -0,0 +1,256 @@
#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)
{
ERR_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)
{
ERR_LOG("ff_linux_bind, fd:%d, addr:%p, addrlen:%u\n", s, addr, addrlen);
SYSCALL(bind, (s, addr, addrlen));
}
int
ff_linux_listen(int s, int backlog)
{
ERR_LOG("ff_linux_listen, fd:%d, backlog:%d\n", s, 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)
{
DEBUG_LOG("ff_linux_accept, fd:%d, addr:%p, len:%p\n", s, addr, addrlen);
SYSCALL(accept, (s, addr, addrlen));
}
int ff_linux_accept4(int s, struct sockaddr *addr,
socklen_t *addrlen, int flags)
{
DEBUG_LOG("ff_linux_accept4, fd:%d, addr:%p, addrlen:%p, flags:%d\n", s, addr, addrlen, flags);
SYSCALL(accept4, (s, addr, addrlen, flags));
}
int ff_linux_connect(int s, const struct sockaddr *addr,
socklen_t addrlen)
{
DEBUG_LOG("ff_linux_connect, fd:%d, addr:%p, addrlen:%u\n", s, addr, addrlen);
SYSCALL(connect, (s, addr, addrlen));
}
ssize_t ff_linux_recv(int s, void *buf, size_t len, int flags)
{
DEBUG_LOG("ff_linux_recv, fd:%d, buf:%p, len:%lu, flags:%d\n", s, buf, len, flags);
SYSCALL(recv, (s, buf, len, flags));
}
ssize_t ff_linux_send(int s, const void *buf, size_t len, int flags)
{
DEBUG_LOG("ff_linux_send, fd:%d, buf:%p, len:%lu, flags:%d\n", s, buf, len, flags);
SYSCALL(send, (s, buf, len, flags));
}
ssize_t ff_linux_read(int s, void *buf, size_t len)
{
DEBUG_LOG("ff_linux_read, fd:%d, buf:%p, len:%lu\n", s, buf, len);
SYSCALL(read, (s, buf, len));
}
ssize_t ff_linux_write(int s, const void *buf, size_t len)
{
DEBUG_LOG("ff_linux_write, fd:%d, buf:%p, len:%lu\n", s, buf, len);
SYSCALL(write, (s, buf, len));
}
ssize_t ff_linux_writev(int s, const struct iovec *iov, int iovcnt)
{
DEBUG_LOG("ff_linux_writev, fd:%d, iov:%p, iovcnt:%d\n", s, iov, iovcnt);
SYSCALL(writev, (s, iov, iovcnt));
}
ssize_t ff_linux_readv(int s, const struct iovec *iov, int iovcnt)
{
DEBUG_LOG("ff_linux_readv, fd:%d, iov:%p, iovcnt:%d\n", s, iov, 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)
{
DEBUG_LOG("ff_linux_sendto, fd:%d, buf:%p, len:%lu, flags:%d, to:%p, tolen:%d\n",
s, buf, len, flags, to, 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)
{
DEBUG_LOG("ff_linux_recvfrom, fd:%d, buf:%p, len:%lu, flags:%d, from:%p, fromlen:%p\n",
s, buf, len, flags, from, fromlen);
SYSCALL(recvfrom, (s, buf, len, flags, from, fromlen));
}
ssize_t ff_linux_sendmsg(int s, const struct msghdr *msg, int flags)
{
DEBUG_LOG("ff_linux_sendmsg, fd:%d, msg:%p, flags:%d\n",
s, msg, flags);
SYSCALL(sendmsg, (s, msg, flags));
}
ssize_t ff_linux_recvmsg(int s, struct msghdr *msg, int flags)
{
DEBUG_LOG("ff_linux_recvmsg, fd:%d, msg:%p, flags:%d\n", s, msg, flags);
SYSCALL(recvmsg, (s, msg, flags))
}
int ff_linux_close(int s)
{
DEBUG_LOG("ff_linux_close, fd:%d\n", 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)
{
ERR_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)
{
ERR_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)
{
DEBUG_LOG("ff_linux_fork\n");
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

View File

@ -0,0 +1,234 @@
#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_NAME_SIZE 32
#define SOCKET_OPS_CONTEXT_NAME "ff_so_context_"
static uint16_t ff_max_so_context = SOCKET_OPS_CONTEXT_MAX_NUM;
__FF_THREAD struct ff_socket_ops_zone *ff_so_zone;
#ifdef FF_MULTI_SC
struct ff_socket_ops_zone *ff_so_zones[SOCKET_OPS_CONTEXT_MAX_NUM] = {NULL};
#endif
static inline int
is_power_of_2(uint64_t n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
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;
}*/
if (!is_power_of_2(count)) {
ERR_LOG("Can not set: count:%d is not power of 2, use default:%d\n",
count, ff_max_so_context);
return -1;
}
if (count > SOCKET_OPS_CONTEXT_MAX_NUM) {
count = SOCKET_OPS_CONTEXT_MAX_NUM;
}
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->mask = so_zone_tmp->count - 1;
so_zone_tmp->free = so_zone_tmp->count;
so_zone_tmp->idx = 0;
memset(so_zone_tmp->inuse, 0, SOCKET_OPS_CONTEXT_MAX_NUM);
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->idx = i;
sc->refcount = 0;
//so_zone_tmp->inuse[i] = 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 idx)
{
struct ff_so_context *sc = NULL;
uint16_t i;
#ifdef FF_MULTI_SC
ff_so_zone = ff_so_zones[idx];
#endif
DEBUG_LOG("proc_id:%d, ff_so_zone:%p\n", idx, ff_so_zone);
if (ff_so_zone == NULL) {
const struct rte_memzone *mz;
char zn[64];
snprintf(zn, sizeof(zn), SOCKET_OPS_ZONE_NAME, idx);
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;
#ifdef FF_MULTI_SC
ff_so_zones[idx] = ff_so_zone;
ERR_LOG("FF_MULTI_SC f_so_zones[%d]:%p\n", idx, ff_so_zones[idx]);
#endif
}
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;
}
for (i = 0; i < ff_so_zone->count; i++) {
uint16_t idx = (ff_so_zone->idx + i) & ff_so_zone->mask;
sc = &ff_so_zone->sc[idx];
if (ff_so_zone->inuse[idx] == 0) {
ff_so_zone->inuse[idx] = 1;
rte_spinlock_init(&sc->lock);
sc->status = FF_SC_IDLE;
sc->refcount = 1;
ff_so_zone->free--;
ff_so_zone->idx = idx + 1;
break;
}
}
if (unlikely(i == ff_so_zone->count)) {
ERR_LOG("Attach memzone failed: instance %d no free context,"
" fetel error of so status, all sc inuse, count:%d, free:%d\n",
idx, ff_so_zone->count, ff_so_zone->free);
sc = NULL;
}
ERR_LOG("attach sc:%p, so count:%d, free:%d, idx:%d, i:%d\n",
sc, ff_so_zone->count, ff_so_zone->free, ff_so_zone->idx, i);
rte_spinlock_unlock(&ff_so_zone->lock);
return sc;
}
void
ff_detach_so_context(struct ff_so_context *sc)
{
ERR_LOG("ff_so_zone:%p, sc:%p\n", ff_so_zone, sc);
if (ff_so_zone == NULL || sc == NULL) {
return;
}
ERR_LOG("detach sc:%p, ops:%d, status:%d, idx:%d, sc->refcount:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->refcount, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
rte_spinlock_lock(&ff_so_zone->lock);
rte_spinlock_lock(&sc->lock);
if (sc->refcount > 1) {
ERR_LOG("sc refcount > 1, to sub it, sc:%p, ops:%d, status:%d, idx:%d, sc->refcount:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->refcount, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
sc->refcount--;
} else {
ERR_LOG("sc refcount is 1, to detach it, sc:%p, ops:%d, status:%d, idx:%d, sc->refcount:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->refcount, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
if (ff_so_zone->inuse[sc->idx] == 1) {
ff_so_zone->inuse[sc->idx] = 0;
ff_so_zone->free++;
ff_so_zone->idx = sc->idx;
}
}
ERR_LOG("detach sc:%p, ops:%d, status:%d, idx:%d, sc->refcount:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->refcount, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
rte_spinlock_unlock(&sc->lock);
rte_spinlock_unlock(&ff_so_zone->lock);
}

View File

@ -0,0 +1,553 @@
#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"
#include "ff_config.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);
#define FF_MAX_BOUND_NUM 8
/* Where to call sem_post in kevent or epoll_wait */
static int sem_flag = 0;
/*
* The event num kevent or epoll_wait returned.
* Use for burst process event in one F-Stack loop to improve performance.
*/
#define EVENT_LOOP_TIMES 32
static int ff_event_loop_nb = 0;
//static int ff_next_event_flag = 0;
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)
{
DEBUG_LOG("ff_sys_read, fd:%d, len:%lu\n", args->fd, args->len);
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)
{
DEBUG_LOG("ff_sys_write, fd:%d, len:%lu\n", args->fd, args->len);
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)
{
DEBUG_LOG("ff_sys_close, fd:%d\n", args->fd);
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)
{
int ret;
DEBUG_LOG("to run ff_epoll_wait, epfd:%d, maxevents:%d, timeout:%d\n",
args->epfd, args->maxevents, args->timeout);
ret = ff_epoll_wait(args->epfd, args->events,
args->maxevents, args->timeout);
/*
* If timeout is 0, and no event triggered,
* no post sem, and next loop will continue to call ff_sys_epoll_wait,
* until some event triggered
*/
if (args->timeout == 0 && ret == 0 && args->maxevents != 0) {
sem_flag = 0;
} else {
sem_flag = 1;
}
return ret;
}
static int
ff_sys_kqueue(struct ff_kqueue_args *args)
{
return ff_kqueue();
}
static int
ff_sys_kevent(struct ff_kevent_args *args)
{
int ret;
ret = ff_kevent(args->kq, args->changelist, args->nchanges,
args->eventlist, args->nevents, args->timeout);
if (args->nchanges) {
args->nchanges = 0;
}
/*
* If timeout is NULL, and no event triggered,
* no post sem, and next loop will continue to call ff_sys_kevent,
* until some event triggered
*/
if (args->timeout == NULL && ret == 0 && args->nevents != 0) {
sem_flag = 0;
} else {
sem_flag = 1;
}
return ret;
}
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;
DEBUG_LOG("ff_so_handler error:%d, ops:%d\n", errno, ops);
return (-1);
}
static inline void
ff_handle_socket_ops(struct ff_so_context *sc)
{
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);
errno = 0;
sc->result = ff_so_handler(sc->ops, sc->args);
sc->error = errno;
DEBUG_LOG("ff_handle_socket_ops error:%d, ops:%d, result:%d\n", errno, sc->ops, sc->result);
if (sc->ops == FF_SO_EPOLL_WAIT || sc->ops == FF_SO_KEVENT) {
/*DEBUG_LOG("ff_event_loop_nb:%d, ff_next_event_flag:%d\n",
ff_event_loop_nb, ff_next_event_flag);
if (ff_event_loop_nb > 0) {
ff_next_event_flag = 1;
} else {
ff_next_event_flag = 0;
}
if (sc->result > 0) {
ff_event_loop_nb = (sc->result * EVENT_LOOP_TIMES);
} else {
ff_event_loop_nb = 0;
}*/
if (sem_flag == 1) {
sc->status = FF_SC_REP;
sem_post(&sc->wait_sem);
} else {
// do nothing with this sc
}
} else {
sc->status = FF_SC_REP;
}
rte_spinlock_unlock(&sc->lock);
}
void
ff_handle_each_context()
{
uint16_t i, nb_handled, tmp;
static uint64_t loop_count = 0;
static uint64_t cur_tsc, diff_tsc, drain_tsc = 0;
if (unlikely(drain_tsc == 0 && ff_global_cfg.dpdk.pkt_tx_delay)) {
drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * ff_global_cfg.dpdk.pkt_tx_delay;
ERR_LOG("ff_global_cfg.dpdk.handle_sc_delay%d, drain_tsc:%lu\n",
ff_global_cfg.dpdk.pkt_tx_delay, drain_tsc);
}
ff_event_loop_nb = 0;
cur_tsc = rte_rdtsc();
rte_spinlock_lock(&ff_so_zone->lock);
assert(ff_so_zone->count >= ff_so_zone->free);
tmp = nb_handled = ff_so_zone->count - ff_so_zone->free;
while(1) {
nb_handled = tmp;
if (nb_handled) {
for (i = 0; i < ff_so_zone->count; i++) {
struct ff_so_context *sc = &ff_so_zone->sc[i];
if ((loop_count & 1048575) == 0) {
DEBUG_LOG("so:%p, so->count:%d,%p, sc:%p, sc->inuse:%d,%p, i:%d, nb:%d, all_nb:%d\n",
ff_so_zone, ff_so_zone->count, &ff_so_zone->count,
sc, ff_so_zone->inuse[i], &ff_so_zone->inuse[i], i, nb_handled, tmp);
}
if (ff_so_zone->inuse[i] == 0) {
continue;
}
/* Dirty read first, and then try to lock sc and real read. */
if (sc->status == FF_SC_REQ) {
ff_handle_socket_ops(sc);
}
nb_handled--;
if (!nb_handled) {
break;
}
}
}
/*if (--ff_event_loop_nb <= 0 || ff_next_event_flag == 1) {
break;
}*/
diff_tsc = rte_rdtsc() - cur_tsc;
DEBUG_LOG("cur_tsc:%lu, diff_tsc:%lu, drain_tsc:%lu\n", cur_tsc, diff_tsc, drain_tsc);
if (diff_tsc >= drain_tsc) {
break;
}
rte_pause();
}
rte_spinlock_unlock(&ff_so_zone->lock);
loop_count++;
DEBUG_LOG("loop_count:%lu, nb:%d, all_nb:%d\n",
loop_count, nb_handled, tmp/*, ff_event_loop_nb, ff_next_event_flag*/);
//, ff_event_loop_nb:%d, ff_next_event_flag:%d
}

View File

@ -0,0 +1,129 @@
#ifndef _FF_SOCKET_OPS_H_
#define _FF_SOCKET_OPS_H_
#include <unistd.h>
#include <semaphore.h>
#include <rte_atomic.h>
#include <rte_spinlock.h>
/*
* Per thread separate initialization dpdk lib and attach sc when needed,
* such as listen same port in different threads, and socket can use in own thread.
*
* Otherwise, one socket can use in all threads.
*/
#ifdef FF_THREAD_SOCKET
#define __FF_THREAD __thread
#else
#define __FF_THREAD
#endif
#define ERR_LOG(fmt, ...) do { \
printf("file:%s, line:%u, fun:%s, pid:%d, "fmt, \
__FILE__, __LINE__, __func__, getpid(), ##__VA_ARGS__); \
} while (0)
#ifdef NDEBUG
#define DEBUG_LOG(...)
#else
#define DEBUG_LOG ERR_LOG
#endif
/* Must be power of 2 */
#define SOCKET_OPS_CONTEXT_MAX_NUM (1 << 5)
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, // 10
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, // 20
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, // 29
};
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, must be power of 2 */
uint8_t count;
uint8_t mask;
/* free number of so_context */
uint8_t free;
uint8_t idx;
/* 1 if used, else 0, most access */
uint8_t inuse[SOCKET_OPS_CONTEXT_MAX_NUM];
struct ff_so_context *sc;
uint8_t padding[16];
} __attribute__((aligned(RTE_CACHE_LINE_SIZE)));
struct ff_so_context {
/* CACHE LINE 0 */
enum FF_SOCKET_OPS ops;
enum FF_SO_CONTEXT_STATUS status;
void *args;
rte_spinlock_t lock;
/* errno if failed */
int error;
/* result of ops processing */
int result;
int idx;
sem_t wait_sem; /* 32 bytes */
/* CACHE LINE 1 */
/* listen fd, refcount.. */
int refcount;
} __attribute__((aligned(RTE_CACHE_LINE_SIZE)));
extern __FF_THREAD struct ff_socket_ops_zone *ff_so_zone;
#ifdef FF_MULTI_SC
extern struct ff_socket_ops_zone *ff_so_zones[SOCKET_OPS_CONTEXT_MAX_NUM];
#endif
/* 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

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/syscall/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;
}

View File

@ -0,0 +1,216 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
//#include "ff_config.h"
//#include "ff_api.h"
#include "ff_event.h"
#include "ff_adapter.h"
#include "ff_hook_syscall.h"
pthread_t hworker;
#define MAX_EVENTS 512
/* kevent set */
struct kevent kevSet;
/* events */
struct kevent events[MAX_EVENTS];
/* kq */
int kq;
int sockfd;
struct timespec timeout = {0, 100000};
static int exit_flag = 0;
char html[] =
"HTTP/1.1 200 OK\r\n"
"Server: F-Stack\r\n"
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 438\r\n"
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
"Connection: keep-alive\r\n"
"Accept-Ranges: bytes\r\n"
"\r\n"
"<!DOCTYPE html>\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Welcome to F-Stack!</title>\r\n"
"<style>\r\n"
" body { \r\n"
" width: 35em;\r\n"
" margin: 0 auto; \r\n"
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
" }\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Welcome to F-Stack!</h1>\r\n"
"\r\n"
"<p>For online documentation and support please refer to\r\n"
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
"\r\n"
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
"</body>\r\n"
"</html>";
void sig_term(int sig)
{
printf("we caught signal %d, to exit helloworld\n", sig);
exit_flag = 1;
alarm_event_sem();
return;
}
void *loop(void *arg)
{
/* Wait for events to happen */
while (!exit_flag) {
/*
* If timeout is NULL, must call alarm_event_sem();
*/
int nevents = kevent(kq, NULL, 0, events, MAX_EVENTS, &timeout);
int i;
if (nevents <= 0) {
if (nevents) {
printf("ff_kevent failed:%d, %s\n", errno,
strerror(errno));
return NULL;
}
//usleep(100);
//sleep(1);
}
//printf("get nevents:%d\n", nevents);
for (i = 0; i < nevents; ++i) {
struct kevent event = events[i];
int clientfd = (int)event.ident;
/* Handle disconnect */
if (event.flags & EV_EOF) {
/* Simply close socket */
close(clientfd);
} else if (clientfd == sockfd) {
int available = (int)event.data;
do {
int nclientfd = accept(clientfd, NULL, NULL);
if (nclientfd < 0) {
printf("ff_accept failed:%d, %s\n", errno,
strerror(errno));
break;
}
/* Add to event list */
EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
if(kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) {
printf("ff_kevent error:%d, %s\n", errno,
strerror(errno));
close(nclientfd);
break;
}
available--;
} while (available);
} else if (event.filter == EVFILT_READ) {
char buf[256];
ssize_t readlen = read(clientfd, buf, sizeof(buf));
ssize_t writelen = write(clientfd, html, sizeof(html) - 1);
if (writelen < 0){
printf("ff_write failed, readlen:%lu, writelen:%lu, :%d, %s\n",
readlen, writelen, errno, strerror(errno));
close(clientfd);
}
} else {
printf("unknown event: %8.8X\n", event.flags);
}
}
}
return NULL;
}
int main(int argc, char * argv[])
{
signal(SIGINT, sig_term);
signal(SIGTERM, sig_term);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("sockfd:%d\n", sockfd);
if (sockfd < 0) {
printf("ff_socket failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
return -1;;
}
/* Set non blocking */
int on = 1;
ioctl(sockfd, FIONBIO, &on);
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("ff_bind failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
close(sockfd);
return -1;
}
ret = listen(sockfd, MAX_EVENTS);
if (ret < 0) {
printf("ff_listen failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
close(sockfd);
return -1;
}
kq = kqueue();
printf("kq:%d\n", kq);
if (kq < 0) {
printf("ff_kqueue failed, errno:%d, %s\n", errno, strerror(errno));
close(sockfd);
return -1;
}
EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
/* Update kqueue */
ret = kevent(kq, &kevSet, 1, NULL, 0, &timeout);
if (ret < 0) {
printf("kevent failed\n");
close(kq);
close(sockfd);
return -1;
}
if(pthread_create(&hworker, NULL, loop, NULL) < 0) {
printf("create loop thread failed., errno:%d/%s\n",
errno, strerror(errno));
close(kq);
close(sockfd);
return -1;
}
pthread_join(hworker, NULL);
close(kq);
close(sockfd);
return 0;
}

View File

@ -0,0 +1,208 @@
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define MAX_WORKERS 128
pthread_t hworker[MAX_WORKERS];
#define MAX_EVENTS 512
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
int epfd;
int sockfd;
static int exit_flag = 0;
char html[] =
"HTTP/1.1 200 OK\r\n"
"Server: F-Stack\r\n"
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 438\r\n"
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
"Connection: keep-alive\r\n"
"Accept-Ranges: bytes\r\n"
"\r\n"
"<!DOCTYPE html>\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Welcome to F-Stack!</title>\r\n"
"<style>\r\n"
" body { \r\n"
" width: 35em;\r\n"
" margin: 0 auto; \r\n"
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
" }\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Welcome to F-Stack!</h1>\r\n"
"\r\n"
"<p>For online documentation and support please refer to\r\n"
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
"\r\n"
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
"</body>\r\n"
"</html>";
void sig_term(int sig)
{
printf("we caught signal %d, to exit helloworld\n", sig);
exit_flag = 1;
//alarm_event_sem();
return;
}
void *loop(void *arg)
{
/* Wait for events to happen */
while (!exit_flag) {
/*
* If not call alarm_event_sem, and epoll_wait timeout is 0,
* it can't exit normal, so timeout can't set to 0.
*/
int nevents = epoll_wait(epfd, events, MAX_EVENTS, 100);
int i;
if (nevents <= 0) {
if (nevents) {
printf("hello world epoll wait ret %d, errno:%d, %s\n",
nevents, errno, strerror(errno));
break;
}
//usleep(100);
sleep(1);
}
//printf("get nevents:%d\n", nevents);
for (i = 0; i < nevents; ++i) {
/* Handle new connect */
if (events[i].data.fd == sockfd) {
while (1) {
int nclientfd = accept(sockfd, NULL, NULL);
printf("accept sockfd:%d, nclientfd:%d, errono:%d/%s\n", sockfd, nclientfd, errno, strerror(errno));
if (nclientfd < 0) {
break;
}
/* Add to event list */
ev.data.fd = nclientfd;
ev.events = EPOLLIN;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) != 0) {
printf("ff_epoll_ctl failed:%d, %s\n",
errno, strerror(errno));
close(nclientfd);
break;
}
}
} else {
if (events[i].events & EPOLLERR ) {
/* Simply close socket */
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
} else if (events[i].events & EPOLLIN) {
char buf[256];
size_t readlen = read( events[i].data.fd, buf, sizeof(buf));
if(readlen > 0) {
write( events[i].data.fd, html, sizeof(html) - 1);
} else {
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
}
} else {
printf("unknown event: %d:%8.8X\n", i, events[i].events);
}
}
}
}
return NULL;
}
int main(int argc, char * argv[])
{
int i, worker_num = 1;
signal(SIGINT, sig_term);
signal(SIGTERM, sig_term);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("sockfd:%d\n", sockfd);
if (sockfd < 0) {
printf("ff_socket failed\n");
return -1;
}
int on = 1;
ioctl(sockfd, FIONBIO, &on);
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("ff_bind failed\n");
close(sockfd);
return -1;
}
ret = listen(sockfd, MAX_EVENTS);
if (ret < 0) {
printf("ff_listen failed\n");
close(sockfd);
return -1;
}
epfd = epoll_create(512);
printf("epfd:%d\n", epfd);
if (epfd <= 0) {
printf("ff_epoll_create failed, errno:%d, %s\n",
errno, strerror(errno));
close(sockfd);
return -1;
}
ev.data.fd = sockfd;
ev.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
if (ret < 0) {
printf("ff_listen failed\n");
close(epfd);
close(sockfd);
return -1;
}
for (i = 0; i < worker_num; i++) {
if(pthread_create(&hworker[i], NULL, loop, (void *)&i) < 0) {
printf("create loop thread failed., errno:%d/%s\n",
errno, strerror(errno));
close(epfd);
close(sockfd);
return -1;
}
}
for (i = 0; i < worker_num; i++) {
pthread_join(hworker[i], NULL);
}
close(epfd);
close(sockfd);
return 0;
}

View File

@ -0,0 +1,255 @@
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define SOCK_FSTACK 0x01000000
#define SOCK_KERNEL 0x02000000
#define MAX_WORKERS 128
pthread_t hworker[MAX_WORKERS];
#define MAX_EVENTS 512
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
int epfd;
int sockfd, sockfd_kernel;
static int exit_flag = 0;
char html[] =
"HTTP/1.1 200 OK\r\n"
"Server: F-Stack\r\n"
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 438\r\n"
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
"Connection: keep-alive\r\n"
"Accept-Ranges: bytes\r\n"
"\r\n"
"<!DOCTYPE html>\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Welcome to F-Stack!</title>\r\n"
"<style>\r\n"
" body { \r\n"
" width: 35em;\r\n"
" margin: 0 auto; \r\n"
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
" }\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Welcome to F-Stack!</h1>\r\n"
"\r\n"
"<p>For online documentation and support please refer to\r\n"
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
"\r\n"
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
"</body>\r\n"
"</html>";
void sig_term(int sig)
{
printf("we caught signal %d, to exit helloworld\n", sig);
exit_flag = 1;
//alarm_event_sem();
return;
}
void *loop(void *arg)
{
/* Wait for events to happen */
while (!exit_flag) {
/*
* If not call alarm_event_sem, and epoll_wait timeout is 0,
* it can't exit normal, so timeout can't set to 0.
*/
int nevents = epoll_wait(epfd, events, MAX_EVENTS, -1);
int i;
if (nevents <= 0) {
if (nevents) {
printf("hello world epoll wait ret %d, errno:%d, %s\n",
nevents, errno, strerror(errno));
break;
}
usleep(100);
//sleep(1);
}
//printf("get nevents:%d\n", nevents);
for (i = 0; i < nevents; ++i) {
/* Handle new connect */
if (events[i].data.fd == sockfd || events[i].data.fd == sockfd_kernel) {
while (1) {
int nclientfd = accept(events[i].data.fd, NULL, NULL);
printf("accept sockfd(_kernel):%d, nclientfd:%d, errono:%d/%s\n", events[i].data.fd, nclientfd, errno, strerror(errno));
if (nclientfd < 0) {
break;
}
/* Add to event list */
ev.data.fd = nclientfd;
ev.events = EPOLLIN;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) != 0) {
printf("ff_epoll_ctl failed:%d, %s\n",
errno, strerror(errno));
close(nclientfd);
break;
}
if (events[i].data.fd == sockfd_kernel) {
break;
}
}
} else {
if (events[i].events & EPOLLERR ) {
/* Simply close socket */
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
} else if (events[i].events & EPOLLIN) {
char buf[256];
size_t readlen = read( events[i].data.fd, buf, sizeof(buf));
if(readlen > 0) {
write( events[i].data.fd, html, sizeof(html) - 1);
} else {
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
}
} else {
printf("unknown event: %d:%8.8X\n", i, events[i].events);
}
}
}
}
return NULL;
}
int main(int argc, char * argv[])
{
int i, worker_num = 1;
signal(SIGINT, sig_term);
signal(SIGTERM, sig_term);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("sockfd:%d\n", sockfd);
if (sockfd < 0) {
printf("ff_socket failed\n");
return -1;
}
int on = 1;
ioctl(sockfd, FIONBIO, &on);
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("ff_bind failed\n");
close(sockfd);
return -1;
}
ret = listen(sockfd, MAX_EVENTS);
if (ret < 0) {
printf("ff_listen failed\n");
close(sockfd);
return -1;
}
sockfd_kernel = socket(AF_INET, SOCK_STREAM | SOCK_KERNEL, 0);
printf("sockfd_kernel:%d\n", sockfd_kernel);
if (sockfd_kernel < 0) {
printf("ff_socket failed\n");
return -1;
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(sockfd_kernel, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("ff_bind failed\n");
close(sockfd);
close(sockfd_kernel);
return -1;
}
ret = listen(sockfd_kernel, MAX_EVENTS);
if (ret < 0) {
printf("ff_listen failed\n");
close(sockfd);
close(sockfd_kernel);
return -1;
}
epfd = epoll_create(512);
printf("epfd:%d\n", epfd);
if (epfd <= 0) {
printf("ff_epoll_create failed, errno:%d, %s\n",
errno, strerror(errno));
close(sockfd);
return -1;
}
ev.data.fd = sockfd;
ev.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
if (ret < 0) {
printf("ff_listen failed\n");
close(epfd);
close(sockfd);
close(sockfd_kernel);
return -1;
}
ev.data.fd = sockfd_kernel;
ev.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd_kernel, &ev);
if (ret < 0) {
printf("ff_listen failed\n");
close(epfd);
close(sockfd);
close(sockfd_kernel);
return -1;
}
for (i = 0; i < worker_num; i++) {
if(pthread_create(&hworker[i], NULL, loop, (void *)&i) < 0) {
printf("create loop thread failed., errno:%d/%s\n",
errno, strerror(errno));
close(epfd);
close(sockfd);
close(sockfd_kernel);
return -1;
}
}
for (i = 0; i < worker_num; i++) {
pthread_join(hworker[i], NULL);
}
close(epfd);
close(sockfd);
close(sockfd_kernel);
return 0;
}

View File

@ -0,0 +1,254 @@
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define MAX_WORKERS 128
pthread_t hworker[MAX_WORKERS];
pthread_spinlock_t worker_lock;
#define MAX_EVENTS 512
static int exit_flag = 0;
char html[] =
"HTTP/1.1 200 OK\r\n"
"Server: F-Stack\r\n"
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 438\r\n"
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
"Connection: keep-alive\r\n"
"Accept-Ranges: bytes\r\n"
"\r\n"
"<!DOCTYPE html>\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Welcome to F-Stack!</title>\r\n"
"<style>\r\n"
" body { \r\n"
" width: 35em;\r\n"
" margin: 0 auto; \r\n"
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
" }\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Welcome to F-Stack!</h1>\r\n"
"\r\n"
"<p>For online documentation and support please refer to\r\n"
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
"\r\n"
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
"</body>\r\n"
"</html>";
void sig_term(int sig)
{
printf("we caught signal %d, to exit helloworld\n", sig);
exit_flag = 1;
//alarm_event_sem();
return;
}
#define SOCK_FSTACK 0x01000000
#define SOCK_KERNEL 0x02000000
void *loop(void *arg)
{
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
int epfd;
int sockfd;
int thread_id;
thread_id = *(int *)arg;
printf("start thread %d\n", thread_id);
sockfd = socket(AF_INET, SOCK_STREAM | SOCK_FSTACK, 0);
printf("thread %d, sockfd:%d\n", thread_id, sockfd);
if (sockfd < 0) {
printf("thread %d, ff_socket failed\n", thread_id);
pthread_spin_unlock(&worker_lock);
return NULL;
}
/* socket will init adapter,so unlock after socket */
pthread_spin_unlock(&worker_lock);
int on = 1;
//ioctl(sockfd, FIONBIO, &on);
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
printf("thread %d, setsockopt SO_REUSEPORT failed\n", thread_id);
return NULL;
}
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("thread %d, ff_bind failed\n", thread_id);
close(sockfd);
return NULL;
}
ret = listen(sockfd, MAX_EVENTS);
if (ret < 0) {
printf("thread %d, ff_listen failed\n", thread_id);
close(sockfd);
return NULL;
}
epfd = epoll_create(512|SOCK_FSTACK);
printf("thread %d, epfd:%d\n", thread_id, epfd);
if (epfd <= 0) {
printf("thread %d, ff_epoll_create failed, errno:%d, %s\n",
thread_id, errno, strerror(errno));
close(sockfd);
return NULL;
}
ev.data.fd = sockfd;
ev.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
if (ret < 0) {
printf("ff_listen failed\n");
close(epfd);
close(sockfd);
return NULL;
}
/* Wait for events to happen */
while (!exit_flag) {
/*
* If not call alarm_event_sem, and epoll_wait timeout is 0,
* it can't exit normal, so timeout can't set to 0.
*/
int nevents = epoll_wait(epfd, events, MAX_EVENTS, 100);
int i;
if (nevents <= 0) {
if (nevents) {
printf("thread %d, hello world epoll wait ret %d, errno:%d, %s\n",
thread_id, nevents, errno, strerror(errno));
break;
}
//usleep(100);
//sleep(1);
}
/*if (nevents > 100) {
printf("error event nb:%d, to exit\n", nevents);
break;
}*/
//printf("thread %d, get nevents:%d\n", thread_id, nevents);
for (i = 0; i < nevents; ++i) {
/* Handle new connect */
if (events[i].data.fd == sockfd) {
//while (1) {
int nclientfd = accept(sockfd, NULL, NULL);
if (nclientfd < 0) {
break;
}
/* Add to event list */
ev.data.fd = nclientfd;
ev.events = EPOLLIN;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) != 0) {
printf("thread %d, ff_epoll_ctl failed:%d, %s\n",
thread_id, errno, strerror(errno));
close(nclientfd);
break;
}
//}
} else {
if (events[i].events & EPOLLERR ) {
/* Simply close socket */
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
} else if (events[i].events & EPOLLIN) {
char buf[256];
size_t readlen = read( events[i].data.fd, buf, sizeof(buf));
if(readlen > 0) {
write( events[i].data.fd, html, sizeof(html) - 1);
} else {
epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
close(events[i].data.fd);
}
} else {
printf("thread %d, unknown event: %8.8X\n", thread_id, events[i].events);
}
}
}
}
close(epfd);
close(sockfd);
return NULL;
}
int main(int argc, char * argv[])
{
int i, worker_num;
signal(SIGINT, sig_term);
signal(SIGTERM, sig_term);
if (argc == 1) {
worker_num = 1;
} else {
worker_num = atoi(argv[1]);
}
printf("to init %d workers.\n", worker_num);
pthread_spin_init(&worker_lock, PTHREAD_PROCESS_PRIVATE);
pthread_spin_lock(&worker_lock);
for (i = 0; i < worker_num; i++) {
if(pthread_create(&hworker[i], NULL, loop, (void *)&i) < 0) {
printf("create loop thread failed., errno:%d/%s\n",
errno, strerror(errno));
pthread_spin_unlock(&worker_lock);
pthread_spin_destroy(&worker_lock);
return -1;
}
if (i > 0) {
cpu_set_t cpuinfo;
int lcore_id = 2 + i;
CPU_ZERO(&cpuinfo);
CPU_SET_S(lcore_id, sizeof(cpuinfo), &cpuinfo);
if(0 != pthread_setaffinity_np(hworker[i], sizeof(cpu_set_t), &cpuinfo))
{
printf("set affinity recver faild\n");
exit(0);
}
printf("set affinity recver sucssed, thread:%d, lcore_id:%d\n", i, lcore_id);
}
pthread_spin_lock(&worker_lock);
//sleep(1);
}
for (i = 0; i < worker_num; i++) {
pthread_join(hworker[i], NULL);
}
pthread_spin_destroy(&worker_lock);
return 0;
}

View File

@ -0,0 +1,262 @@
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <errno.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
//#include "ff_config.h"
//#include "ff_api.h"
#include "ff_event.h"
#include "ff_adapter.h"
#include "ff_hook_syscall.h"
#define MAX_WORKERS 128
pthread_t hworker[MAX_WORKERS];
pthread_spinlock_t worker_lock;
#define MAX_EVENTS 512
/* 100 ms */
struct timespec timeout = {0, 100000000};
static int exit_flag = 0;
char html[] =
"HTTP/1.1 200 OK\r\n"
"Server: F-Stack\r\n"
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 438\r\n"
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
"Connection: keep-alive\r\n"
"Accept-Ranges: bytes\r\n"
"\r\n"
"<!DOCTYPE html>\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Welcome to F-Stack!</title>\r\n"
"<style>\r\n"
" body { \r\n"
" width: 35em;\r\n"
" margin: 0 auto; \r\n"
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
" }\r\n"
"</style>\r\n"
"</head>\r\n"
"<body>\r\n"
"<h1>Welcome to F-Stack!</h1>\r\n"
"\r\n"
"<p>For online documentation and support please refer to\r\n"
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
"\r\n"
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
"</body>\r\n"
"</html>";
void sig_term(int sig)
{
printf("we caught signal %d, to exit helloworld\n", sig);
exit_flag = 1;
//alarm_event_sem();
return;
}
void *loop(void *arg)
{
/* kevent set */
struct kevent kevSet;
/* events */
struct kevent events[MAX_EVENTS];
/* kq */
int kq;
int sockfd;
int thread_id;
thread_id = *(int *)arg;
printf("start thread %d\n", thread_id);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
printf("thread %d, sockfd:%d\n", thread_id, sockfd);
if (sockfd < 0) {
printf("thread %d, ff_socket failed\n", thread_id);
pthread_spin_unlock(&worker_lock);
return NULL;
}
/* socket will init adapter,so unlock after socket */
pthread_spin_unlock(&worker_lock);
int on = 1;
ioctl(sockfd, FIONBIO, &on);
struct sockaddr_in my_addr;
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(80);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd, (const struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) {
printf("thread %d, ff_bind failed\n", thread_id);
close(sockfd);
return NULL;
}
ret = listen(sockfd, MAX_EVENTS);
if (ret < 0) {
printf("thread %d, ff_listen failed\n", thread_id);
close(sockfd);
return NULL;
}
kq = kqueue();
printf("thread %d, kq:%d\n", thread_id, kq);
if (kq < 0) {
printf("thread %d, ff_kqueue failed, errno:%d, %s\n", thread_id, errno, strerror(errno));
close(sockfd);
return NULL;
}
EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
/* Update kqueue */
ret = kevent(kq, &kevSet, 1, NULL, 0, &timeout);
if (ret < 0) {
printf("thread %d, kevent failed\n", thread_id);
close(kq);
close(sockfd);
return NULL;
}
/* Wait for events to happen */
while (!exit_flag) {
/*
* If not call alarm_event_sem, and epoll_wait timeout is NULL,
* it can't exit normal, so timeout can't set to NULL.
*/
int nevents = kevent(kq, NULL, 0, events, MAX_EVENTS, &timeout);
int i;
if (nevents <= 0) {
if (nevents) {
printf("thread %d, ff_kevent failed:%d, %s\n", thread_id, errno,
strerror(errno));
return NULL;
}
//usleep(100);
//sleep(1);
}
//printf("thread %d, get nevents:%d\n", thread_id, nevents);
for (i = 0; i < nevents; ++i) {
struct kevent event = events[i];
int clientfd = (int)event.ident;
/* Handle disconnect */
if (event.flags & EV_EOF) {
/* Simply close socket */
close(clientfd);
} else if (clientfd == sockfd) {
int available = (int)event.data;
do {
int nclientfd = accept(clientfd, NULL, NULL);
if (nclientfd < 0) {
printf("thread %d, ff_accept failed:%d, %s\n", thread_id, errno,
strerror(errno));
break;
}
/* Add to event list */
EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
if(kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) {
printf("thread %d, ff_kevent error:%d, %s\n", thread_id, errno,
strerror(errno));
close(nclientfd);
break;
}
available--;
} while (available);
} else if (event.filter == EVFILT_READ) {
char buf[256];
ssize_t readlen = read(clientfd, buf, sizeof(buf));
ssize_t writelen = write(clientfd, html, sizeof(html) - 1);
if (writelen < 0){
printf("thread %d, ff_write failed, readlen:%lu, writelen:%lu, :%d, %s\n",
thread_id, readlen, writelen, errno, strerror(errno));
close(clientfd);
}
} else {
printf("thread %d, unknown event: %d:%8.8X\n", thread_id, i, event.flags);
}
}
}
close(kq);
close(sockfd);
return NULL;
}
int main(int argc, char * argv[])
{
int i, worker_num;
signal(SIGINT, sig_term);
signal(SIGTERM, sig_term);
if (argc == 1) {
worker_num = 1;
} else {
worker_num = atoi(argv[1]);
}
printf("to init %d workers.\n", worker_num);
pthread_spin_init(&worker_lock, PTHREAD_PROCESS_PRIVATE);
pthread_spin_lock(&worker_lock);
for (i = 0; i < worker_num; i++) {
if(pthread_create(&hworker[i], NULL, loop, (void *)&i) < 0) {
printf("create loop thread failed., errno:%d/%s\n",
errno, strerror(errno));
pthread_spin_unlock(&worker_lock);
pthread_spin_destroy(&worker_lock);
return -1;
}
if (i > 0) {
cpu_set_t cpuinfo;
int lcore_id = 2 + i;
CPU_ZERO(&cpuinfo);
CPU_SET_S(lcore_id, sizeof(cpuinfo), &cpuinfo);
if(0 != pthread_setaffinity_np(hworker[i], sizeof(cpu_set_t), &cpuinfo))
{
printf("set affinity recver faild\n");
exit(0);
}
printf("set affinity recver sucssed, thread:%d, lcore_id:%d\n", i, lcore_id);
}
pthread_spin_lock(&worker_lock);
}
for (i = 0; i < worker_num; i++) {
pthread_join(hworker[i], NULL);
}
pthread_spin_destroy(&worker_lock);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -10,7 +10,7 @@ endif
PKGCONF ?= pkg-config PKGCONF ?= pkg-config
CFLAGS += -O -gdwarf-2 $(shell $(PKGCONF) --cflags libdpdk) CFLAGS += -O0 -g -gdwarf-2 $(shell $(PKGCONF) --cflags libdpdk)
LIBS+= $(shell $(PKGCONF) --static --libs libdpdk) LIBS+= $(shell $(PKGCONF) --static --libs libdpdk)
LIBS+= -L${FF_PATH}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive LIBS+= -L${FF_PATH}/lib -Wl,--whole-archive,-lfstack,--no-whole-archive