summaryrefslogtreecommitdiff
path: root/accel-dp
diff options
context:
space:
mode:
Diffstat (limited to 'accel-dp')
-rw-r--r--accel-dp/CMakeLists.txt49
-rw-r--r--accel-dp/af_packet.c82
-rw-r--r--accel-dp/common.h25
-rw-r--r--accel-dp/conf_file.c364
-rw-r--r--accel-dp/conf_file.h24
-rw-r--r--accel-dp/ctrl.c347
-rw-r--r--accel-dp/dev.c94
-rw-r--r--accel-dp/dev.h33
-rw-r--r--accel-dp/distributor.c156
-rw-r--r--accel-dp/eth_dev.c118
-rw-r--r--accel-dp/event.c284
-rw-r--r--accel-dp/event.h44
-rw-r--r--accel-dp/if_dp.h77
-rw-r--r--accel-dp/init.h18
l---------accel-dp/iputils.c1
l---------accel-dp/iputils.h1
-rw-r--r--accel-dp/kni_dev.c213
-rw-r--r--accel-dp/kni_dev.h9
l---------accel-dp/libnetlink.c1
l---------accel-dp/libnetlink.h1
-rw-r--r--accel-dp/list.h251
-rw-r--r--accel-dp/log.c350
-rw-r--r--accel-dp/log.h61
-rw-r--r--accel-dp/log_file.c246
-rw-r--r--accel-dp/main.c378
-rw-r--r--accel-dp/sock.h40
26 files changed, 3267 insertions, 0 deletions
diff --git a/accel-dp/CMakeLists.txt b/accel-dp/CMakeLists.txt
new file mode 100644
index 0000000..0506615
--- /dev/null
+++ b/accel-dp/CMakeLists.txt
@@ -0,0 +1,49 @@
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3")
+
+add_definitions("-DACCEL_DP")
+
+include_directories(${DPDK}/build/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+find_library(rte_eal NAMES librte_eal.a PATHS ${DPDK}/build/lib)
+find_library(rte_malloc NAMES librte_malloc.a PATHS ${DPDK}/build/lib)
+find_library(rte_mbuf NAMES librte_mbuf.a PATHS ${DPDK}/build/lib)
+find_library(rte_mempool NAMES librte_mempool.a PATHS ${DPDK}/build/lib)
+find_library(rte_ring NAMES librte_ring.a PATHS ${DPDK}/build/lib)
+find_library(ethdev NAMES libethdev.a PATHS ${DPDK}/build/lib)
+find_library(rte_kni NAMES librte_kni.a PATHS ${DPDK}/build/lib)
+find_library(rte_distributor NAMES librte_distributor.a PATHS ${DPDK}/build/lib)
+find_library(rte_pmd_virtio NAMES librte_pmd_virtio.a PATHS ${DPDK}/build/lib)
+
+add_executable(accel-dp
+ main.c
+ conf_file.c
+ event.c
+ ctrl.c
+ af_packet.c
+ dev.c
+ eth_dev.c
+ kni_dev.c
+ distributor.c
+
+ log.c
+ log_file.c
+
+ libnetlink.c
+ iputils.c
+)
+
+target_link_libraries(accel-dp dl pthread
+ -Wl,-whole-archive
+ ${rte_eal}
+ ${rte_mbuf}
+ ${rte_mempool}
+ ${rte_ring}
+ ${rte_malloc}
+ ${ethdev}
+ ${rte_kni}
+ ${rte_distributor}
+ ${rte_pmd_virtio}
+ -Wl,-no-whole-archive
+)
+
diff --git a/accel-dp/af_packet.c b/accel-dp/af_packet.c
new file mode 100644
index 0000000..89a3c09
--- /dev/null
+++ b/accel-dp/af_packet.c
@@ -0,0 +1,82 @@
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <linux/if_packet.h>
+
+#include <rte_malloc.h>
+
+#include "sock.h"
+#include "common.h"
+#include "dev.h"
+
+struct packet_priv {
+ int type;
+};
+
+static int packet_socket(struct sock *sk, int type, int proto)
+{
+ struct packet_priv *priv = rte_malloc(NULL, sizeof(*sk->priv), 0);
+
+ if (!priv)
+ return sock_errno(sk, ENOMEM);
+
+ priv->type = type;
+
+ sk->priv = priv;
+
+ return sock_errno(sk, 0);
+}
+
+static int packet_bind(struct sock *sk, const struct sockaddr *a, socklen_t addrlen)
+{
+ struct sockaddr_ll *addr = (struct sockaddr_ll *)a;
+ struct net_device *dev = NULL;
+
+ if (addrlen != sizeof(*addr))
+ return sock_errno(sk, EINVAL);
+
+ if (addr->sll_ifindex) {
+ dev = netdev_get_by_index(addr->sll_ifindex);
+ if (!dev)
+ return sock_errno(sk, ENODEV);
+ }
+
+ return sock_errno(sk, 0);
+}
+
+static int packet_recv(struct sock *sk, size_t len, int flags, socklen_t addrlen)
+{
+
+ return sock_errno(sk, EAGAIN);
+}
+
+static int packet_send(struct sock *sk, void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
+{
+
+ return sock_errno(sk, 0);
+}
+
+static void packet_close(struct sock *sk)
+{
+ rte_free(sk->priv);
+}
+
+static const struct proto_ops proto = {
+ .socket = packet_socket,
+ .bind = packet_bind,
+ .listen = sock_no_listen,
+ .connect = sock_no_connect,
+ .recv = packet_recv,
+ .send = packet_send,
+ .ioctl = sock_no_ioctl,
+ .close = packet_close,
+};
+
+static void __init init()
+{
+ sock_register_proto(PF_PACKET, SOCK_RAW, 0, &proto);
+}
+
diff --git a/accel-dp/common.h b/accel-dp/common.h
new file mode 100644
index 0000000..62b47e3
--- /dev/null
+++ b/accel-dp/common.h
@@ -0,0 +1,25 @@
+#ifndef __COMMON_H
+#define __COMMON_H
+
+#define __init __attribute__((constructor))
+#define __exit __attribute__((destructor))
+#define __export __attribute__((visibility("default")))
+
+#undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define likely(x) __builtin_expect((x),1)
+#define unlikely(x) __builtin_expect((x),0)
+
+extern int sock_fd;
+
+#endif
+
diff --git a/accel-dp/conf_file.c b/accel-dp/conf_file.c
new file mode 100644
index 0000000..c22cfd5
--- /dev/null
+++ b/accel-dp/conf_file.c
@@ -0,0 +1,364 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "conf_file.h"
+
+struct conf_ctx {
+ const char *fname;
+ FILE *file;
+ int line;
+ struct conf_opt **list;
+ int options:1;
+};
+
+static struct conf_sect *sect_head;
+static struct conf_sect *sect_tail;
+
+static char* skip_space(char *str);
+static char* skip_word(char *str);
+
+static struct conf_sect *find_sect(const char *name);
+static struct conf_sect *create_sect(const char *name);
+static int sect_add_item(struct conf_ctx *ctx, const char *name, char *val, char *raw);
+static struct conf_opt *find_item(struct conf_opt *list, const char *name);
+static int load_file(struct conf_ctx *ctx);
+
+static char *buf;
+static struct conf_sect *cur_sect;
+
+static int open_ctx(struct conf_ctx *ctx, const char *fname, struct conf_opt **list)
+{
+ ctx->file = fopen(fname, "r");
+ if (!ctx->file)
+ return -1;
+
+ ctx->fname = fname;
+ ctx->line = 0;
+ ctx->list = ctx->list;
+ ctx->options = 0;
+
+ return 0;
+}
+
+static void close_ctx(struct conf_ctx *ctx)
+{
+ fclose(ctx->file);
+}
+
+static int load_file(struct conf_ctx *ctx)
+{
+ char *str, *str2, *raw;
+ int len;
+
+ while(1) {
+ if (!fgets(buf, 1024, ctx->file))
+ break;
+ ctx->line++;
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[--len] = 0;
+
+ while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
+ buf[--len] = 0;
+
+ str = skip_space(buf);
+ if (*str == '#' || *str == 0)
+ continue;
+
+ if (strncmp(str, "$include", 8) == 0) {
+ struct conf_ctx ctx1;
+ int r;
+ str = skip_word(str);
+ str = skip_space(str);
+
+ if (open_ctx(&ctx1, str, ctx->list))
+ break;
+
+ r = load_file(&ctx1);
+
+ close_ctx(&ctx1);
+
+ if (r)
+ break;
+
+ ctx->list = ctx1.list;
+
+ continue;
+ }
+
+ if (*str == '[') {
+ for (str2 = ++str; *str2 && *str2 != ']'; str2++);
+ if (*str2 != ']') {
+ fprintf(stderr, "conf_file:%s:%i: sintax error\n", ctx->fname, ctx->line);
+ return -1;
+ }
+
+ if (ctx->options) {
+ fprintf(stderr, "conf_file:%s:%i: cann't open section inside option\n", ctx->fname, ctx->line);
+ return -1;
+ }
+
+ *str2 = 0;
+ cur_sect = find_sect(str);
+ if (!cur_sect)
+ cur_sect = create_sect(str);
+ ctx->list = (struct conf_opt **)&cur_sect->opt;
+ continue;
+ }
+
+ if (!cur_sect) {
+ fprintf(stderr, "conf_file:%s:%i: no section opened\n", ctx->fname, ctx->line);
+ return -1;
+ }
+
+ if (*str == '}') {
+ if (ctx->options)
+ return 0;
+
+ fprintf(stderr, "conf_file:%s:%i: sintax error\n", ctx->fname, ctx->line);
+ return -1;
+ }
+
+ raw = strdup(str);
+ str2 = skip_word(str);
+ if (*str2 == ' ') {
+ *str2 = 0;
+ ++str2;
+ }
+
+ str2 = skip_space(str2);
+ if (*str2 == '=' || *str2 == ',') {
+ *str2 = 0;
+ str2 = skip_space(str2 + 1);
+ if (*str2 && *(str2 + 1) && *str2 == '$' && *(str2 + 1) == '{') {
+ char *s;
+ struct conf_opt *opt;
+ for (s = str2 + 2; *s && *s != '}'; s++);
+ if (*s == '}') {
+ *s = 0;
+ str2 += 2;
+ }
+ opt = find_item(cur_sect->opt, str2);
+ if (!opt) {
+ fprintf(stderr, "conf_file:%s:%i: parent option not found\n", ctx->fname, ctx->line);
+ return -1;
+ }
+ str2 = (char *)opt->val;
+ }
+ } else
+ str2 = NULL;
+
+ if (sect_add_item(ctx, str, str2, raw))
+ return -1;
+ }
+
+ return 0;
+}
+
+/*static void print_items(struct list_head *items, int dep)
+{
+ struct conf_option_t *opt;
+ int i;
+
+ list_for_each_entry(opt, items, entry) {
+ for (i = 0; i < dep; i++)
+ printf("\t");
+ printf("%s=%s\n", opt->name, opt->val);
+ print_items(&opt->items, dep + 1);
+ }
+}
+
+static void print_conf()
+{
+ struct sect_t *s;
+
+ list_for_each_entry(s, &sections, entry) {
+ printf("[%s]\n", s->sect->name);
+ print_items(&s->sect->items, 0);
+ }
+}*/
+
+static void free_items(struct conf_opt *opt)
+{
+ struct conf_opt *next;
+
+ for (next = opt->next; opt; opt = next) {
+ if (opt->child)
+ free_items(opt->child);
+ free(opt->name);
+ free(opt->raw);
+ if (opt->val)
+ free(opt->val);
+ free((void *)opt);
+ }
+}
+
+static void conf_clear(struct conf_sect *s)
+{
+ struct conf_sect *next;
+
+ for (next = s->next; s; s = next) {
+ if (s->opt)
+ free_items(s->opt);
+ free(s->name);
+ free((void *)s);
+ }
+}
+
+int conf_load(const char *fname)
+{
+ struct conf_sect *head = sect_head;
+ struct conf_ctx ctx;
+ int r;
+
+ if (open_ctx(&ctx, fname, NULL))
+ return -1;
+
+ cur_sect = NULL;
+ sect_head = NULL;
+
+ buf = malloc(1024);
+
+ r = load_file(&ctx);
+
+ free(buf);
+
+ close_ctx(&ctx);
+
+ if (r)
+ sect_head = head;
+ else if (head)
+ conf_clear(head);
+
+ return r;
+}
+
+static char* skip_space(char *str)
+{
+ for (; *str && (*str == ' ' || *str == '\t'); str++);
+ return str;
+}
+
+static char* skip_word(char *str)
+{
+ for (; *str && (*str != ' ' && *str != '\t' && *str != '='); str++);
+ return str;
+}
+
+static struct conf_sect *find_sect(const char *name)
+{
+ struct conf_sect *s;
+
+ for (s = sect_head; s; s = s->next) {
+ if (strcmp(s->name, name) == 0)
+ return s;
+ }
+
+ return NULL;
+}
+
+static struct conf_sect *create_sect(const char *name)
+{
+ struct conf_sect *s = malloc(sizeof(struct conf_sect));
+
+ s->name = strdup(name);
+ s->next = NULL;
+ s->opt = NULL;
+
+ if (!sect_head)
+ sect_head = s;
+ else
+ sect_tail->next = s;
+
+ sect_tail = s;
+
+ return s;
+}
+
+static int sect_add_item(struct conf_ctx *ctx, const char *name, char *val, char *raw)
+{
+ struct conf_opt *opt = malloc(sizeof(struct conf_opt));
+ int r = 0;
+ int chld = 0;
+
+ if (val) {
+ int len = strlen(val);
+ if (val[len - 1] == '{') {
+ chld = 1;
+ val[--len] = 0;
+
+ while (--len >= 0 && (val[len] == ' ' || val[len] == '\t'));
+
+ if (len >= 0)
+ val[len + 1] = 0;
+ else
+ val = NULL;
+ }
+ }
+
+ opt->name = strdup(name);
+ opt->val = val ? strdup(val) : NULL;
+ opt->raw = raw;
+ opt->next = NULL;
+ opt->child = NULL;
+
+ *ctx->list = opt;
+ ctx->list = &opt->next;
+
+ if (chld) {
+ struct conf_opt **list = ctx->list;
+ ctx->list = &opt->child;
+ ctx->options = 1;
+ r = load_file(ctx);
+ ctx->options = 0;
+ ctx->list = list;
+ }
+
+ return r;
+}
+
+static struct conf_opt *find_item(struct conf_opt *list, const char *name)
+{
+ struct conf_opt *opt;
+
+ for (opt = list; opt; opt = opt->next) {
+ if (strcmp(opt->name, name) == 0)
+ return opt;
+ }
+
+ return NULL;
+}
+
+struct conf_sect* conf_get_sect(const char *name)
+{
+ return find_sect(name);
+}
+
+const char *conf_get_opt(const char *sect, const char *name)
+{
+ struct conf_opt *opt;
+ struct conf_sect *s = conf_get_sect(sect);
+
+ if (!s)
+ return NULL;
+
+ opt = find_item(s->opt, name);
+ if (!opt)
+ return NULL;
+
+ return opt->val;
+}
+
+const char *conf_get_subopt(const struct conf_opt *opt, const char *name)
+{
+ if (!opt->child)
+ return NULL;
+
+ opt = find_item(opt->child, name);
+
+ return opt ? opt->val : NULL;
+}
+
diff --git a/accel-dp/conf_file.h b/accel-dp/conf_file.h
new file mode 100644
index 0000000..7110303
--- /dev/null
+++ b/accel-dp/conf_file.h
@@ -0,0 +1,24 @@
+#ifndef __CONF_FILE_H
+#define __CONF_FILE_H
+
+struct conf_opt {
+ struct conf_opt *next;
+ char *name;
+ char *val;
+ char *raw;
+ struct conf_opt *child;
+};
+
+struct conf_sect {
+ struct conf_sect *next;
+ char *name;
+ struct conf_opt *opt;
+};
+
+struct conf_sect *conf_get_sect(const char *name);
+const char *conf_get_opt(const char *sect, const char *name);
+const char *conf_get_subopt(const struct conf_opt *opt, const char *name);
+
+int conf_load(const char *fname);
+
+#endif
diff --git a/accel-dp/ctrl.c b/accel-dp/ctrl.c
new file mode 100644
index 0000000..b816d82
--- /dev/null
+++ b/accel-dp/ctrl.c
@@ -0,0 +1,347 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <rte_malloc.h>
+
+#include "init.h"
+#include "common.h"
+#include "conf_file.h"
+#include "event.h"
+#include "sock.h"
+
+#include "if_dp.h"
+
+struct protosw {
+ struct list_head entry;
+ int domain;
+ int type;
+ int proto;
+ const struct proto_ops *ops;
+};
+
+static struct event_handler ctrl_hnd;
+
+static LIST_HEAD(proto_list);
+
+void sock_register_proto(int domain, int type, int proto, const struct proto_ops *ops)
+{
+ struct list_head *pos = proto_list.next;
+ struct protosw *p;
+
+ while (pos != &proto_list) {
+ p = list_entry(pos, typeof(*p), entry);
+ if (p->domain == domain && type && !p->type)
+ break;
+ pos = pos->next;
+ }
+
+ p = malloc(sizeof(*p));
+ p->domain = domain;
+ p->type = type;
+ p->proto = proto;
+
+ list_add_tail(&p->entry, pos);
+}
+
+static int sock_send_errno(int fd, int err)
+{
+ struct msg_result msg = {
+ .err = err,
+ .len = 0,
+ .addrlen = 0,
+ };
+
+ return write(fd, &msg, sizeof(msg)) != sizeof(msg);
+}
+
+int sock_errno(struct sock *sk, int err)
+{
+ sk->res->err = 0;
+ sk->res->len = 0;
+ sk->res->addrlen = 0;
+ return sizeof(*sk->res);
+}
+
+static int msg_socket(struct sock *sk, void *buf, int size)
+{
+ struct msg_socket *msg = (struct msg_socket *)buf;
+ struct protosw *p;
+ int dom = 0;
+
+ list_for_each_entry(p, &proto_list, entry) {
+ if (p->domain != msg->domain)
+ continue;
+
+ dom = 1;
+
+ if (p->type && p->type != msg->type)
+ continue;
+
+ if (p->proto && p->proto != msg->proto)
+ continue;
+
+ sk->ops = p->ops;
+
+ break;
+ }
+
+ if (!sk->ops) {
+ sock_send_errno(sk->hnd.fd, dom ? EPROTONOSUPPORT : EAFNOSUPPORT);
+ return -1;
+ }
+
+ return sk->ops->socket(sk, msg->type, msg->proto);
+}
+
+static int msg_connect(struct sock *sk, void *buf, int size)
+{
+ struct msg_connect *msg = (struct msg_connect *)buf;
+
+ assert(sk->ops);
+ /*if (unlikely(!sk->ops)) {
+ sock_send_errno(sk->hnd.fd, ENOTSOCK);
+ return -1;
+ }*/
+
+ return sk->ops->connect(sk, (struct sockaddr *)msg->addr, msg->addrlen);
+}
+
+static int msg_bind(struct sock *sk, void *buf, int size)
+{
+ struct msg_bind *msg = (struct msg_bind *)buf;
+
+ assert(sk->ops);
+ /*if (unlikely(!sk->ops)) {
+ sock_send_errno(sk->hnd.fd, ENOTSOCK);
+ return -1;
+ }*/
+
+ return sk->ops->bind(sk, (struct sockaddr *)msg->addr, msg->addrlen);
+}
+
+static int msg_listen(struct sock *sk, void *buf, int size)
+{
+ struct msg_listen *msg = (struct msg_listen *)buf;
+
+ assert(sk->ops);
+ /*if (unlikely(!sk->ops)) {
+ sock_send_errno(sk->hnd.fd, ENOTSOCK);
+ return -1;
+ }*/
+
+ return sk->ops->listen(sk, msg->backlog);
+}
+
+static int msg_recv(struct sock *sk, void *buf, int size)
+{
+ struct msg_recv *msg = (struct msg_recv *)buf;
+
+ assert(sk->ops);
+ /*if (unlikely(!sk->ops)) {
+ sock_send_errno(sk->hnd.fd, ENOTSOCK);
+ return -1;
+ }*/
+
+ return sk->ops->recv(sk, msg->len, msg->flags, msg->addrlen);
+}
+
+static int msg_send(struct sock *sk, void *buf, int size)
+{
+ struct msg_send *msg = (struct msg_send *)buf;
+ struct sockaddr *addr = (struct sockaddr *)(msg + 1);
+
+ assert(sk->ops);
+ /*if (unlikely(!sk->ops)) {
+ sock_send_errno(sk->hnd.fd, ENOTSOCK);
+ return -1;
+ }*/
+
+ return sk->ops->send(sk, (char *)(msg + 1) + msg->addrlen, msg->len, msg->flags, addr, msg->addrlen);
+}
+
+static int msg_ioctl(struct sock *sk, void *buf, int size)
+{
+ struct msg_ioctl *msg = (struct msg_ioctl *)buf;
+
+ assert(sk->ops);
+
+ return sk->ops->ioctl(sk, msg->request, msg->arg);
+}
+
+static int msg_ppp_open(struct sock *sk, void *buf, int size)
+{
+ struct msg_socket *msg = (struct msg_socket *)buf;
+ msg->domain = PF_PPP;
+ msg->type = SOCK_DGRAM;
+ msg->proto = 0;
+
+ return msg_socket(sk, buf, size);
+}
+
+static int msg_sock_ioctl(struct sock *sk, void *buf, int size)
+{
+ //struct msg_ioctl *msg = (struct msg_ioctl *)buf;
+
+ return 0;
+}
+
+typedef int (*handler)(struct sock *sk, void *buf, int size);
+static handler msg_hnd[__MSG_MAX_ID] = {
+ [MSG_SOCKET] = msg_socket,
+ [MSG_CONNECT] = msg_connect,
+ [MSG_BIND] = msg_bind,
+ [MSG_LISTEN] = msg_listen,
+ [MSG_RECV] = msg_recv,
+ [MSG_SEND] = msg_send,
+ [MSG_IOCTL] = msg_ioctl,
+ [MSG_PPP_OPEN] = msg_ppp_open,
+ [MSG_SOCK_IOCTL] = msg_sock_ioctl,
+};
+
+int sock_no_listen(struct sock *sk, int backlog)
+{
+ return sock_send_errno(sk->hnd.fd, ENOSYS);
+}
+
+int sock_no_connect(struct sock *sk, const struct sockaddr *addr, socklen_t addrlen)
+{
+ return sock_send_errno(sk->hnd.fd, ENOSYS);
+}
+
+int sock_no_ioctl(struct sock *sk, unsigned long request, void *arg)
+{
+ return sock_send_errno(sk->hnd.fd, ENOSYS);
+}
+
+static int sock_read(struct event_handler *h)
+{
+ struct sock *sk = container_of(h, typeof(*sk), hnd);
+ char *buf = rte_malloc(NULL, SOCK_BUF_SIZE, 0);
+ int r;
+ struct msg_hdr *hdr = (struct msg_hdr *)buf;
+
+ if (!buf)
+ goto close;
+
+ r = read(h->fd, buf, SOCK_BUF_SIZE);
+
+ if (r < sizeof(*hdr))
+ goto close;
+
+ if (hdr->id >= __MSG_MAX_ID) {
+ if (sock_send_errno(h->fd, ENOSYS))
+ goto close;
+ }
+
+ sk->res = (struct msg_result *)buf;
+ r = msg_hnd[hdr->id](sk, buf, r);
+
+ if (likely(r > 0)) {
+ if (unlikely(write(h->fd, buf, r) != r))
+ goto close;
+ }
+
+ rte_free(buf);
+
+ if (likely(r == 0))
+ return 0;
+
+close:
+ if (sk->ops)
+ sk->ops->close(sk);
+
+ event_del_handler(h, 1);
+
+ if (buf)
+ rte_free(buf);
+
+ return 1;
+}
+
+static int ctrl_accept(struct event_handler *h)
+{
+ int sock;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ struct sock *sk;
+
+ while (1) {
+ addrlen = sizeof(addr);
+ sock = accept(h->fd, (struct sockaddr *)&addr, &addrlen);
+ if (sock < 0)
+ break;
+
+ sk = rte_malloc(NULL, sizeof(*sk), 0);
+ if (sk) {
+ sk->hnd.fd = sock;
+ sk->hnd.read = sock_read;
+ sk->ops = NULL;
+
+ fcntl(sock, F_SETFL, O_NONBLOCK);
+
+ event_add_handler(&sk->hnd, EVENT_READ);
+ } else
+ close(h->fd);
+ }
+
+ return 0;
+}
+
+int ctrl_init()
+{
+ const char *opt = conf_get_opt("core", "ctrl-socket");
+ int sock;
+ struct sockaddr_un addr;
+
+ if (event_init())
+ return -1;
+
+ if (!opt) {
+ fprintf(stderr, "ctrl-socket not specified\n");
+ return -1;
+ }
+
+ if (strlen(opt) >= sizeof(addr.sun_path)) {
+ fprintf(stderr, "ctrl-socket path is too large\n");
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, opt);
+
+ unlink(opt);
+
+ sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) {
+ fprintf(stderr, "ctrl-socket: %s\n", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ if (listen(sock, 1024)) {
+ perror("listen");
+ close(sock);
+ return -1;
+ }
+
+ fcntl(sock, F_SETFL, O_NONBLOCK);
+
+ ctrl_hnd.fd = sock;
+ ctrl_hnd.read = ctrl_accept;
+ event_add_handler(&ctrl_hnd, EVENT_READ);
+
+ return 0;
+}
+
diff --git a/accel-dp/dev.c b/accel-dp/dev.c
new file mode 100644
index 0000000..d31773d
--- /dev/null
+++ b/accel-dp/dev.c
@@ -0,0 +1,94 @@
+#include <string.h>
+
+#include <rte_malloc.h>
+
+#include "init.h"
+#include "dev.h"
+
+#define DEV_MAX 65536
+
+static struct net_device **dev_list;
+static int next_idx = 1;
+
+struct net_device *netdev_get_by_index(int id)
+{
+ struct net_device *dev;
+
+ if (id <= 0 || id >= DEV_MAX)
+ return NULL;
+
+ dev = dev_list[id];
+
+ if (dev)
+ ++dev->refs;
+
+ return dev;
+}
+
+struct net_device *netdev_alloc(const char *name, int priv_size, void (*setup)(struct net_device *dev))
+{
+ struct net_device *dev;
+ int i;
+
+ for (i = 0; i < DEV_MAX; i++) {
+ if (dev_list[i] && !strcmp(dev_list[i]->name, name))
+ return NULL;
+ }
+
+ for (; next_idx < DEV_MAX; next_idx++) {
+ if (!dev_list[next_idx])
+ break;
+ }
+
+ if (next_idx == DEV_MAX) {
+ for (next_idx = 1; next_idx < DEV_MAX; next_idx++) {
+ if (!dev_list[next_idx])
+ break;
+ }
+
+ if (next_idx == DEV_MAX)
+ return NULL;
+ }
+
+ dev = rte_malloc(NULL, sizeof(*dev) + priv_size, 0);
+ strcpy(dev->name, name);
+ dev->index = next_idx;
+
+ dev->refs = 1;
+ dev->destructor = netdev_free;
+
+ if (setup)
+ setup(dev);
+
+ dev_list[next_idx] = dev;
+
+ if (++next_idx == DEV_MAX)
+ next_idx = 1;
+
+ return dev;
+}
+
+void netdev_unregister(struct net_device *dev)
+{
+ dev_list[dev->index] = NULL;
+
+ netdev_put(dev);
+}
+
+void netdev_free(struct net_device *dev)
+{
+ rte_free(dev);
+}
+
+void netdev_put(struct net_device *dev)
+{
+ if (--dev->refs == 0)
+ dev->destructor(dev);
+}
+
+static void init()
+{
+ dev_list = rte_zmalloc(0, DEV_MAX * sizeof(void *), 0);
+}
+
+DEFINE_INIT(1, init);
diff --git a/accel-dp/dev.h b/accel-dp/dev.h
new file mode 100644
index 0000000..1039a17
--- /dev/null
+++ b/accel-dp/dev.h
@@ -0,0 +1,33 @@
+#ifndef __NET_DEVICE_H
+#define __NET_DEVICE_H
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+struct rte_mbuf;
+
+struct net_device {
+ char name[IFNAMSIZ];
+ int index;
+
+ unsigned char hwaddr[6];
+
+ int refs;
+
+ void (*xmit)(struct rte_mbuf *mbuf, struct net_device *dev);
+ void (*destructor)(struct net_device *dev);
+};
+
+struct net_device *netdev_get_by_index(int id);
+void netdev_put(struct net_device *dev);
+void netdev_free(struct net_device *dev);
+struct net_device *netdev_alloc(const char *name, int priv_size, void (*setup)(struct net_device *dev));
+void netdev_unregister(struct net_device *dev);
+
+static inline void *netdev_priv(struct net_device *dev)
+{
+ return dev + 1;
+}
+
+#endif
diff --git a/accel-dp/distributor.c b/accel-dp/distributor.c
new file mode 100644
index 0000000..970f322
--- /dev/null
+++ b/accel-dp/distributor.c
@@ -0,0 +1,156 @@
+#include <rte_config.h>
+#include <rte_memory.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_errno.h>
+#include <rte_distributor.h>
+#include <rte_debug.h>
+
+#include "init.h"
+#include "kni_dev.h"
+#include "event.h"
+#include "log.h"
+
+#define BURST_SIZE 32
+
+#define MBUF_DROP 255
+
+static struct rte_distributor *d;
+static int term;
+static int port_cnt;
+
+struct xmit_buf {
+ struct rte_mbuf *bufs[BURST_SIZE];
+ int cnt;
+};
+
+int distributor_init(int ded)
+{
+ d = rte_distributor_create("distributor", rte_socket_id(), rte_lcore_count() - ded);
+ return d == NULL;
+}
+
+static void flush_port(int port, struct xmit_buf *xb)
+{
+ int nb;
+
+ if (likely(port < port_cnt))
+ nb = rte_eth_tx_burst(port, 0, xb->bufs, xb->cnt);
+ else
+ nb = kni_dev_tx_burst(port - port_cnt, 0, xb->bufs, xb->cnt);
+
+ if (unlikely(nb < xb->cnt)) {
+ do {
+ rte_pktmbuf_free(xb->bufs[nb]);
+ } while (++nb < xb->cnt);
+ }
+}
+
+static void distributor_tx(struct rte_mbuf **bufs, int nb, struct xmit_buf *xmit_bufs)
+{
+ struct rte_mbuf *mb;
+ int i, p;
+
+ _mm_prefetch(bufs[0], 0);
+ _mm_prefetch(bufs[1], 0);
+ _mm_prefetch(bufs[2], 0);
+ for (i = 0; i < nb; i++) {
+ _mm_prefetch(bufs[i + 3], 0);
+
+ mb = bufs[i];
+
+ p = mb->port;
+
+ if (likely(p != MBUF_DROP)) {
+ struct xmit_buf *xb = &xmit_bufs[p];
+ xb->bufs[xb->cnt++] = mb;
+ if (xb->cnt == BURST_SIZE)
+ flush_port(p, xb);
+ } else
+ rte_pktmbuf_free(mb);
+ }
+}
+
+void distributor_loop(int chk_event)
+{
+ int kni_port_cnt = kni_dev_count();
+ struct rte_mbuf *bufs[BURST_SIZE*2];
+ int port, nb, i;
+ struct xmit_buf *xmit_bufs;
+ int tot_port_cnt;
+ struct xmit_buf *xb;
+
+ port_cnt = rte_eth_dev_count();
+ tot_port_cnt = port_cnt + kni_port_cnt;
+
+ xmit_bufs = rte_malloc(NULL, (tot_port_cnt * sizeof(struct xmit_buf)), 0);
+
+ for (i = 0; i < tot_port_cnt; i++)
+ xmit_bufs[i].cnt = 0;
+
+ while (!term) {
+ for (port = 0; port < port_cnt; port++) {
+ nb = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE);
+
+ if (likely(nb))
+ rte_distributor_process(d, bufs, nb);
+
+ nb = rte_distributor_returned_pkts(d, bufs, BURST_SIZE*2);
+
+ if (likely(nb))
+ distributor_tx(bufs, nb, xmit_bufs);
+ }
+
+ for (port = 0; port < kni_port_cnt; port++) {
+ nb = kni_dev_rx_burst(port, 0, bufs, BURST_SIZE);
+
+ if (likely(nb))
+ rte_distributor_process(d, bufs, nb);
+
+ nb = rte_distributor_returned_pkts(d, bufs, BURST_SIZE*2);
+
+ if (likely(nb))
+ distributor_tx(bufs, nb, xmit_bufs);
+ }
+
+ _mm_prefetch(&xmit_bufs[0], 0);
+ _mm_prefetch(&xmit_bufs[1], 0);
+ _mm_prefetch(&xmit_bufs[2], 0);
+ for (i = 0; i < tot_port_cnt; i++) {
+ _mm_prefetch(&xmit_bufs[i + 3], 0);
+
+ xb = &xmit_bufs[i];
+
+ if (likely(xb->cnt))
+ flush_port(i, xb);
+ }
+
+ if (chk_event)
+ event_process(0);
+ }
+}
+
+int lcore_worker(void *a)
+{
+ struct rte_mbuf *mb = NULL;
+
+ while (!term) {
+ mb = rte_distributor_get_pkt(d, 0, mb);
+ mb->port = MBUF_DROP;
+ }
+
+ return 0;
+}
+
+int lcore_distributor(void *a)
+{
+ distributor_loop(0);
+
+ return 0;
+}
diff --git a/accel-dp/eth_dev.c b/accel-dp/eth_dev.c
new file mode 100644
index 0000000..c99edba
--- /dev/null
+++ b/accel-dp/eth_dev.c
@@ -0,0 +1,118 @@
+#include <unistd.h>
+
+#include <rte_config.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_errno.h>
+
+#include "init.h"
+#include "conf_file.h"
+#include "dev.h"
+
+#define TX_RING_SIZE 512
+#define RX_RING_SIZE 512
+
+struct ethdev {
+ int port;
+};
+
+static struct ethdev **dev_list;
+
+static void ethdev_xmit(struct rte_mbuf *mbuf, struct net_device *dev)
+{
+ struct ethdev *eth_dev = netdev_priv(dev);
+
+ mbuf->port = eth_dev->port;
+}
+
+int eth_dev_init(struct rte_mempool *mbuf_pool)
+{
+ struct conf_sect *s = conf_get_sect("interface");
+ struct conf_opt *opt;
+ int i, cnt = rte_eth_dev_count();
+ struct rte_eth_dev_info info;
+ char busid[64];
+ const char *opt1;
+ int rxd, txd;
+ struct net_device *dev;
+ struct ethdev *eth_dev;
+ struct ether_addr addr;
+ struct rte_eth_link link;
+ struct rte_eth_conf conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .max_rx_pkt_len = ETHER_MAX_LEN + 8,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ };
+
+ dev_list = rte_malloc(NULL, cnt * sizeof(void *), 0);
+
+ for (i = 0; i < cnt; i++) {
+ rte_eth_dev_info_get(i, &info);
+
+ sprintf(busid, "%04x:%02x:%02x.%i", info.pci_dev->addr.domain, info.pci_dev->addr.bus, info.pci_dev->addr.devid, info.pci_dev->addr.function);
+
+ for (opt = s->opt; opt; opt = opt->next) {
+ const char *opt_busid = conf_get_subopt(opt, "busid");
+ if (!strcmp(opt_busid, busid) || !strcmp(opt_busid, busid + 5))
+ break;
+ }
+
+ opt1 = conf_get_subopt(opt, "txd");
+ if (opt1)
+ txd = atoi(opt1);
+ else
+ txd = TX_RING_SIZE;
+
+ opt1 = conf_get_subopt(opt, "rxd");
+ if (opt1)
+ rxd = atoi(opt1);
+ else
+ rxd = RX_RING_SIZE;
+
+ if (rte_eth_dev_configure(i, 1, 1, &conf)) {
+ fprintf(stderr, "%s: %s\n", busid, rte_strerror(rte_errno));
+ return -1;
+ }
+
+ if (rte_eth_rx_queue_setup(i, 0, rxd, rte_eth_dev_socket_id(i), NULL, mbuf_pool)) {
+ fprintf(stderr, "%s: %s\n", busid, rte_strerror(rte_errno));
+ return -1;
+ }
+
+ if (rte_eth_tx_queue_setup(i, 0, txd, rte_eth_dev_socket_id(i), NULL)) {
+ fprintf(stderr, "%s: %s\n", busid, rte_strerror(rte_errno));
+ return -1;
+ }
+
+ if (rte_eth_dev_start(i)) {
+ fprintf(stderr, "%s: %s\n", busid, rte_strerror(rte_errno));
+ return -1;
+ }
+
+ rte_eth_link_get_nowait(i, &link);
+ if (!link.link_status) {
+ sleep(1);
+ rte_eth_link_get_nowait(i, &link);
+ }
+
+ if (!link.link_status)
+ printf("%s: link down\n", opt->name);
+
+ rte_eth_macaddr_get(i, &addr);
+
+ dev = netdev_alloc(opt->name, sizeof(*eth_dev), NULL);
+ dev->xmit = ethdev_xmit;
+ memcpy(dev->hwaddr, addr.addr_bytes, ETHER_ADDR_LEN);
+ eth_dev = netdev_priv(dev);
+ eth_dev->port = i;
+
+ dev_list[i] = eth_dev;
+ }
+
+ return 0;
+}
diff --git a/accel-dp/event.c b/accel-dp/event.c
new file mode 100644
index 0000000..c313df8
--- /dev/null
+++ b/accel-dp/event.c
@@ -0,0 +1,284 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "event.h"
+
+#define MAX_EVENT 128
+
+static int epoll_fd;
+static struct epoll_event *epoll_events;
+static struct event_deferred *deferred_list;
+static LIST_HEAD(timers);
+static LIST_HEAD(handlers);
+static int term;
+
+int event_init(void)
+{
+ epoll_fd = epoll_create(1);
+ if (epoll_fd < 0) {
+ perror("epoll_create");
+ return -1;
+ }
+
+ if (!epoll_events)
+ epoll_events = malloc(MAX_EVENT * sizeof(struct epoll_event));
+
+ term = 0;
+
+ INIT_LIST_HEAD(&timers);
+ INIT_LIST_HEAD(&handlers);
+
+ return 0;
+}
+
+static int get_timeout()
+{
+ struct event_handler *h;
+ struct timespec ts;
+
+ if (list_empty(&timers))
+ return -1;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ h = list_entry(timers.next, typeof(*h), entry2);
+
+ if (ts.tv_sec > h->timeout_ts.tv_sec || (ts.tv_sec == h->timeout_ts.tv_sec && ts.tv_nsec >= h->timeout_ts.tv_nsec))
+ return 0;
+
+ return (h->timeout_ts.tv_sec - ts.tv_sec)*1000 + (h->timeout_ts.tv_nsec - ts.tv_nsec)/1000000;
+}
+
+static void check_timeout()
+{
+ struct event_handler *h;
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ while (!list_empty(&timers)) {
+ h = list_entry(timers.next, typeof(*h), entry2);
+
+ if (ts.tv_sec > h->timeout_ts.tv_sec || (ts.tv_sec == h->timeout_ts.tv_sec && ts.tv_nsec >= h->timeout_ts.tv_nsec)) {
+ list_del(&h->entry2);
+ h->entry2.next = NULL;
+ h->timeout(h);
+ } else
+ break;
+ }
+}
+
+void event_process(int timeout)
+{
+ int i, n;
+ struct event_handler *h;
+ struct event_deferred *d;
+ uint32_t events;
+ struct list_head *pos, *t;
+
+ if (timeout == -1)
+ timeout = get_timeout();
+ else if (timeout > 0) {
+ int t = get_timeout();
+ if (t >= 0 && t < timeout)
+ timeout = t;
+ }
+
+ n = epoll_wait(epoll_fd, epoll_events, MAX_EVENT, timeout);
+ if (n <= 0)
+ return;
+
+ for(i = 0; i < n && !term; i++) {
+ h = (struct event_handler *)epoll_events[i].data.ptr;
+
+ if (h->fd == -1)
+ continue;
+
+ if (!h->epoll_event.events)
+ continue;
+
+ events = epoll_events[i].events & h->epoll_event.events;
+
+ if ((events & (EPOLLIN|EPOLLHUP)) && h->read) {
+ if (h->read(h))
+ continue;
+ }
+
+ if ((events & (EPOLLOUT|EPOLLHUP)) && h->write) {
+ if (h->write(h))
+ continue;
+ }
+ }
+
+ check_timeout();
+
+ while (deferred_list) {
+ d = deferred_list;
+ deferred_list = deferred_list->next;
+ d->fn(d);
+ }
+
+ if (term) {
+ list_for_each_safe(pos, t, &handlers) {
+ h = list_entry(pos, typeof(*h), entry);
+ if (h->close)
+ h->close(h);
+ }
+
+ while (deferred_list) {
+ d = deferred_list;
+ deferred_list = deferred_list->next;
+ d->fn(d);
+ }
+
+ close(epoll_fd);
+ }
+}
+
+void event_loop()
+{
+ while (!term)
+ event_process(-1);
+}
+
+void event_terminate(void)
+{
+ term = 1;
+}
+
+int event_add_handler(struct event_handler *h, int mode)
+{
+ list_add_tail(&h->entry, &handlers);
+
+ h->epoll_event.data.ptr = h;
+ h->epoll_event.events = EPOLLET;
+
+ if (mode & EVENT_READ)
+ h->epoll_event.events |= EPOLLIN;
+
+ if (mode & EVENT_WRITE)
+ h->epoll_event.events |= EPOLLOUT;
+
+ return epoll_ctl(epoll_fd, EPOLL_CTL_ADD, h->fd, &h->epoll_event);
+}
+
+int event_mod_handler(struct event_handler *h, int mode)
+{
+ h->epoll_event.data.ptr = h;
+ h->epoll_event.events = EPOLLET;
+
+ if (mode & EVENT_READ)
+ h->epoll_event.events |= EPOLLIN;
+
+ if (mode & EVENT_WRITE)
+ h->epoll_event.events |= EPOLLOUT;
+
+ return epoll_ctl(epoll_fd, EPOLL_CTL_MOD, h->fd, &h->epoll_event);
+}
+
+int event_enable_handler(struct event_handler *h, int mode)
+{
+ uint32_t events = h->epoll_event.events;
+
+ if (mode & EVENT_READ)
+ h->epoll_event.events |= EPOLLIN;
+
+ if (mode & EVENT_WRITE)
+ h->epoll_event.events |= EPOLLOUT;
+
+ if (events == h->epoll_event.events)
+ return 0;
+
+ return epoll_ctl(epoll_fd, EPOLL_CTL_MOD, h->fd, &h->epoll_event);
+}
+
+int event_disable_handler(struct event_handler *h, int mode)
+{
+ uint32_t events = h->epoll_event.events;
+
+ if (mode & EVENT_READ)
+ h->epoll_event.events &= ~EPOLLIN;
+
+ if (mode & EVENT_WRITE)
+ h->epoll_event.events &= ~EPOLLOUT;
+
+ if (events == h->epoll_event.events)
+ return 0;
+
+ return epoll_ctl(epoll_fd, EPOLL_CTL_MOD, h->fd, &h->epoll_event);
+}
+
+int event_del_handler(struct event_handler *h, int c)
+{
+ if (!h->entry.next)
+ return 0;
+
+ if (h->entry2.next) {
+ list_del(&h->entry2);
+ h->entry2.next = NULL;
+ }
+
+ list_del(&h->entry);
+
+ if (c) {
+ close(h->fd);
+ h->fd = -1;
+ return 0;
+ }
+
+ h->epoll_event.events = 0;
+
+ return epoll_ctl(epoll_fd, EPOLL_CTL_DEL, h->fd, NULL);
+}
+
+void event_set_timeout(struct event_handler *h, int msec)
+{
+ struct event_handler *h1;
+ struct list_head *pos;
+ struct timespec ts;
+
+ if (h->entry2.next)
+ list_del(&h->entry2);
+
+ if (msec == -1) {
+ h->entry2.next = NULL;
+ return;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ ts.tv_sec += msec / 1000;
+ ts.tv_nsec += (msec % 1000) * 1000000;
+
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ h->timeout_ts = ts;
+
+ pos = timers.prev;
+
+ while (pos != &timers) {
+ h1 = list_entry(pos, typeof(*h1), entry2);
+
+ if (ts.tv_sec > h1->timeout_ts.tv_sec || (ts.tv_sec == h1->timeout_ts.tv_sec && ts.tv_nsec >= h1->timeout_ts.tv_nsec))
+ break;
+
+ pos = pos->prev;
+ }
+
+ list_add(&h->entry2, pos);
+}
+
+void event_add_deferred(struct event_deferred *d)
+{
+ d->next = deferred_list;
+ deferred_list = d;
+}
+
diff --git a/accel-dp/event.h b/accel-dp/event.h
new file mode 100644
index 0000000..fefb099
--- /dev/null
+++ b/accel-dp/event.h
@@ -0,0 +1,44 @@
+#ifndef __EVENT_H__
+#define __EVENT_H__
+
+#include <sys/epoll.h>
+#include "list.h"
+
+#define EVENT_READ 1
+#define EVENT_WRITE 2
+
+struct event_handler {
+ struct list_head entry;
+ struct list_head entry2;
+ struct timespec timeout_ts;
+ int fd;
+ struct epoll_event epoll_event;
+ int (*read)(struct event_handler *);
+ int (*write)(struct event_handler *);
+ void (*timeout)(struct event_handler *);
+ void (*close)(struct event_handler *);
+};
+
+struct event_deferred {
+ struct event_deferred *next;
+ void (*fn)(struct event_deferred *);
+};
+
+int event_init(void);
+void event_loop();
+void event_process(int timeout);
+void event_terminate(void);
+int event_add_handler(struct event_handler *h, int mode);
+int event_enable_handler(struct event_handler *h, int mode);
+int event_disable_handler(struct event_handler *h, int mode);
+int event_mod_handler(struct event_handler *h, int mode);
+int event_del_handler(struct event_handler *h, int close);
+void event_set_timeout(struct event_handler *h, int msec);
+void event_add_deferred(struct event_deferred *d);
+
+static inline void event_init_handler(struct event_handler *h)
+{
+ h->entry.next = NULL;
+}
+
+#endif
diff --git a/accel-dp/if_dp.h b/accel-dp/if_dp.h
new file mode 100644
index 0000000..5c209a7
--- /dev/null
+++ b/accel-dp/if_dp.h
@@ -0,0 +1,77 @@
+#ifndef __IF_DP_H
+#define __IF_DP_H
+
+#include <stdint.h>
+
+enum {
+ MSG_SOCKET,
+ MSG_CONNECT,
+ MSG_BIND,
+ MSG_LISTEN,
+ MSG_RECV,
+ MSG_SEND,
+ MSG_IOCTL,
+ MSG_PPP_OPEN,
+ MSG_SOCK_IOCTL,
+ __MSG_MAX_ID
+};
+
+#define MSG_MAX_ID (__MSG_MAX_ID - 1)
+
+struct msg_hdr {
+ uint8_t id;
+};
+
+struct msg_socket {
+ uint8_t id;
+ int domain;
+ int type;
+ int proto;
+};
+
+struct msg_connect {
+ uint8_t id;
+ socklen_t addrlen;
+ char addr[0];
+};
+
+struct msg_bind {
+ uint8_t id;
+ socklen_t addrlen;
+ char addr[0];
+};
+
+struct msg_listen {
+ uint8_t id;
+ int backlog;
+};
+
+struct msg_recv {
+ uint8_t id;
+ size_t len;
+ int flags;
+ socklen_t addrlen;
+};
+
+struct msg_send {
+ uint8_t id;
+ size_t len;
+ int flags;
+ socklen_t addrlen;
+};
+
+struct msg_ioctl {
+ uint8_t id;
+ unsigned long request;
+ char arg[0];
+};
+
+struct msg_result {
+ int err;
+ ssize_t len;
+ socklen_t addrlen;
+ struct sockaddr_storage ss;
+};
+
+#endif
+
diff --git a/accel-dp/init.h b/accel-dp/init.h
new file mode 100644
index 0000000..28c8781
--- /dev/null
+++ b/accel-dp/init.h
@@ -0,0 +1,18 @@
+#ifndef __INIT_H
+#define __INIT_H
+
+struct rte_mempool;
+
+int ctrl_init();
+int kni_dev_init(struct rte_mempool *mbuf_pool);
+int eth_dev_init(struct rte_mempool *mbuf_pool);
+
+int distributor_init(int ded);
+void distributor_loop(int chk_event);
+int lcore_worker(void *a);
+int lcore_distributor(void *a);
+
+void register_init(int order, void (*func)(void));
+#define DEFINE_INIT(o, func) static void __attribute__((constructor)) __init__(void){register_init(o,func);}
+
+#endif
diff --git a/accel-dp/iputils.c b/accel-dp/iputils.c
new file mode 120000
index 0000000..ca75da2
--- /dev/null
+++ b/accel-dp/iputils.c
@@ -0,0 +1 @@
+../accel-pppd/libnetlink/iputils.c \ No newline at end of file
diff --git a/accel-dp/iputils.h b/accel-dp/iputils.h
new file mode 120000
index 0000000..a36b224
--- /dev/null
+++ b/accel-dp/iputils.h
@@ -0,0 +1 @@
+../accel-pppd/libnetlink/iputils.h \ No newline at end of file
diff --git a/accel-dp/kni_dev.c b/accel-dp/kni_dev.c
new file mode 100644
index 0000000..bafe976
--- /dev/null
+++ b/accel-dp/kni_dev.c
@@ -0,0 +1,213 @@
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <linux/if.h>
+
+#include <rte_config.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_kni.h>
+#include <rte_malloc.h>
+#include <rte_errno.h>
+
+#include "init.h"
+#include "conf_file.h"
+#include "common.h"
+#include "dev.h"
+#include "kni_dev.h"
+
+#include "iputils.h"
+
+struct knidev {
+ int port;
+ int xport;
+ struct net_device *dev;
+ struct rte_kni *kni;
+ int ifindex;
+};
+
+static int kni_cnt;
+static struct knidev **dev_list;
+
+int kni_dev_count()
+{
+ return kni_cnt;
+}
+
+uint16_t kni_dev_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, const uint16_t nb_pkts)
+{
+ return rte_kni_rx_burst(dev_list[port_id]->kni, rx_pkts, nb_pkts);
+}
+
+uint16_t kni_dev_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return rte_kni_tx_burst(dev_list[port_id]->kni, tx_pkts, nb_pkts);
+}
+
+static void knidev_xmit(struct rte_mbuf *mbuf, struct net_device *dev)
+{
+ struct knidev *kni_dev = netdev_priv(dev);
+
+ mbuf->port = kni_dev->xport;
+}
+
+static int kni_change_mtu(uint8_t port, unsigned mtu)
+{
+ return 0;
+}
+
+static int kni_config_network_if(uint8_t port, uint8_t if_up)
+{
+ return 0;
+}
+
+static int parse_ip_addr(const char *str, in_addr_t *addr, int *mask)
+{
+ char *ptr = strchr(str, '/');
+ char tmp[32];
+
+ if (ptr) {
+ memcpy(tmp, str, ptr - str);
+ tmp[ptr - str] = 0;
+ *addr = inet_addr(tmp);
+ *mask = atoi(ptr + 1);
+ if (*mask <= 0 || *mask > 32)
+ return -1;
+ } else {
+ *addr = inet_addr(str);
+ *mask = 32;
+ }
+
+ return *addr == INADDR_NONE;
+}
+
+struct ifconfig_arg {
+ struct knidev *dev;
+ struct conf_opt *opt;
+ int err;
+};
+
+static void *kni_ifconfig(void *a)
+{
+ struct ifconfig_arg *arg = a;
+ struct knidev *dev = arg->dev;
+ struct conf_opt *opt = arg->opt;
+ struct ifreq ifr;
+ const char *opt1;
+ in_addr_t addr;
+ int mask;
+
+ strcpy(ifr.ifr_name, opt->name);
+
+ if (ioctl(sock_fd, SIOCGIFINDEX, &ifr, sizeof(ifr))) {
+ fprintf(stderr, "%s: SIOCGIFINDEX: %s\n", opt->name, strerror(errno));
+ arg->err = errno;
+ return NULL;
+ }
+
+ dev->ifindex = ifr.ifr_ifindex;
+
+ ioctl(sock_fd, SIOCGIFFLAGS, &ifr, sizeof(ifr));
+
+ ifr.ifr_flags |= IFF_UP | IFF_NOARP;
+
+ while (ioctl(sock_fd, SIOCSIFFLAGS, &ifr, sizeof(ifr)))
+ sleep(1);
+
+ opt1 = conf_get_subopt(opt, "ip-addr");
+ if (opt1) {
+ if (parse_ip_addr(opt1, &addr, &mask)) {
+ arg->err = EINVAL;
+ return NULL;
+ }
+
+ ipaddr_add(dev->ifindex, addr, mask);
+ }
+
+ arg->err = 0;
+
+ return NULL;
+}
+
+int kni_dev_init(struct rte_mempool *mbuf_pool)
+{
+ struct conf_sect *s = conf_get_sect("interface");
+ struct conf_opt *opt;
+ struct rte_kni_conf conf;
+ struct rte_kni_ops ops;
+ struct rte_kni *kni;
+ struct net_device *dev;
+ struct knidev *knidev;
+ pthread_t tid;
+ struct ifconfig_arg arg;
+ int i = 0, x = rte_eth_dev_count();
+
+ for (opt = s->opt; opt; opt = opt->next) {
+ const char *busid = conf_get_subopt(opt, "busid");
+ if (!strcmp(busid, "kni"))
+ kni_cnt++;
+ }
+
+ if (!kni_cnt)
+ return 0;
+
+ rte_kni_init(kni_cnt);
+
+ dev_list = rte_malloc(NULL, kni_cnt * sizeof(void *), 0);
+
+ memset(&conf, 0, sizeof(conf));
+ memset(&ops, 0, sizeof(ops));
+
+ ops.change_mtu = kni_change_mtu;
+ ops.config_network_if = kni_config_network_if;
+
+ for (opt = s->opt; opt; opt = opt->next) {
+ const char *busid = conf_get_subopt(opt, "busid");
+ if (strcmp(busid, "kni"))
+ continue;
+
+ strcpy(conf.name, opt->name);
+ conf.group_id = i;
+ conf.mbuf_size = ETHER_MAX_LEN + 8;
+
+ ops.port_id = i;
+
+ kni = rte_kni_alloc(mbuf_pool, &conf, &ops);
+
+ if (!kni) {
+ fprintf(stderr, "failed to create %s\n", opt->name);
+ return -1;
+ }
+
+ dev = netdev_alloc(opt->name, sizeof(*knidev), NULL);
+ dev->xmit = knidev_xmit;
+ knidev = netdev_priv(dev);
+ knidev->port = i;
+ knidev->xport = i + x;
+ knidev->dev = dev;
+ knidev->kni = kni;
+
+ dev_list[i] = knidev;
+
+ arg.dev = knidev;
+ arg.opt = opt;
+ arg.err = -1;
+
+ pthread_create(&tid, NULL, kni_ifconfig, &arg);
+
+ while (arg.err == -1)
+ rte_kni_handle_request(kni);
+
+ pthread_join(tid, NULL);
+
+ if (arg.err != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/accel-dp/kni_dev.h b/accel-dp/kni_dev.h
new file mode 100644
index 0000000..78fa448
--- /dev/null
+++ b/accel-dp/kni_dev.h
@@ -0,0 +1,9 @@
+#ifndef __KNI_DEV_H
+#define __KNI_DEV_H
+
+int kni_dev_count();
+uint16_t kni_dev_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, const uint16_t nb_pkts);
+uint16_t kni_dev_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+
+#endif
+
diff --git a/accel-dp/libnetlink.c b/accel-dp/libnetlink.c
new file mode 120000
index 0000000..98931f9
--- /dev/null
+++ b/accel-dp/libnetlink.c
@@ -0,0 +1 @@
+../accel-pppd/libnetlink/libnetlink.c \ No newline at end of file
diff --git a/accel-dp/libnetlink.h b/accel-dp/libnetlink.h
new file mode 120000
index 0000000..86c8798
--- /dev/null
+++ b/accel-dp/libnetlink.h
@@ -0,0 +1 @@
+../accel-pppd/libnetlink/libnetlink.h \ No newline at end of file
diff --git a/accel-dp/list.h b/accel-dp/list.h
new file mode 100644
index 0000000..2ffa7f0
--- /dev/null
+++ b/accel-dp/list.h
@@ -0,0 +1,251 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#undef LIST_HEAD
+
+//#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
+
+//#include <linux/prefetch.h>
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+typedef struct list_head {
+ struct list_head *next, *prev;
+} list_t;
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+
+static void inline prefetch(void *p){}
+
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = (void *) 0;
+ entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+//#endif /* __KERNEL__ || _LVM_H_INCLUDE */
+
+#endif
diff --git a/accel-dp/log.c b/accel-dp/log.c
new file mode 100644
index 0000000..bd0d6bb
--- /dev/null
+++ b/accel-dp/log.c
@@ -0,0 +1,350 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#include <rte_malloc.h>
+
+#include "init.h"
+#include "common.h"
+#include "conf_file.h"
+
+#include "log.h"
+
+#define LOG_MSG 0
+#define LOG_ERROR 1
+#define LOG_WARN 2
+#define LOG_INFO1 3
+#define LOG_INFO2 4
+#define LOG_DEBUG 5
+
+struct _log_msg {
+ struct list_head entry;
+ int level;
+ struct timeval timestamp;
+ struct list_head chunks;
+ unsigned int refs;
+};
+
+static int log_level;
+
+static LIST_HEAD(targets);
+
+static pthread_key_t pth_key;
+static __thread struct _log_msg *cur_msg;
+static __thread char *stat_buf;
+
+static FILE *emerg_file;
+static FILE *debug_file;
+
+static void _log_free_msg(struct _log_msg *msg);
+static struct log_msg *clone_msg(struct _log_msg *msg);
+static int add_msg(struct _log_msg *msg, const char *buf, int len);
+static void write_msg(FILE *f, struct _log_msg *msg);
+
+static void stat_buf_free(void *ptr)
+{
+ rte_free(ptr);
+}
+
+void log_append(const char *str, int len)
+{
+ struct log_target *t;
+ struct log_msg *m;
+
+ if (!cur_msg)
+ return;
+
+ if (add_msg(cur_msg, str, len))
+ goto out;
+
+ if (str[len - 1] != '\n')
+ return;
+
+ if (debug_file)
+ write_msg(debug_file, cur_msg);
+
+ list_for_each_entry(t, &targets, entry) {
+ m = clone_msg(cur_msg);
+ if (!m)
+ break;
+ t->log(m);
+ }
+
+out:
+ _log_free_msg(cur_msg);
+ cur_msg = NULL;
+}
+
+static void do_log(int level, const char *fmt, va_list ap)
+{
+ if (!cur_msg) {
+ cur_msg = rte_malloc(NULL, sizeof(*cur_msg), 0);
+ if (!cur_msg)
+ return;
+ INIT_LIST_HEAD(&cur_msg->chunks);
+ cur_msg->refs = 1;
+ cur_msg->level = level;
+ gettimeofday(&cur_msg->timestamp, NULL);
+ }
+
+ if (!stat_buf) {
+ stat_buf = rte_malloc(NULL, LOG_MAX_SIZE + 1, 0);
+ pthread_setspecific(pth_key, stat_buf);
+ }
+
+ vsnprintf(stat_buf, LOG_MAX_SIZE, fmt, ap);
+ log_append(stat_buf, strlen(stat_buf));
+}
+
+void log_error(const char *fmt,...)
+{
+ if (log_level >= LOG_ERROR) {
+ va_list ap;
+ va_start(ap,fmt);
+ do_log(LOG_ERROR, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void log_warn(const char *fmt,...)
+{
+ if (log_level >= LOG_WARN) {
+ va_list ap;
+ va_start(ap,fmt);
+ do_log(LOG_WARN, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void log_info1(const char *fmt,...)
+{
+ if (log_level >= LOG_INFO1) {
+ va_list ap;
+ va_start(ap, fmt);
+ do_log(LOG_INFO1, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void log_info2(const char *fmt,...)
+{
+ if (log_level >= LOG_INFO2) {
+ va_list ap;
+ va_start(ap, fmt);
+ do_log(LOG_INFO2, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void log_debug(const char *fmt,...)
+{
+ if (log_level >= LOG_DEBUG) {
+ va_list ap;
+ va_start(ap, fmt);
+ do_log(LOG_DEBUG, fmt, ap);
+ va_end(ap);
+ }
+}
+
+void log_debug2(const char *fmt,...)
+{
+ va_list ap;
+ if (!debug_file)
+ return;
+ va_start(ap, fmt);
+ vfprintf(debug_file, fmt, ap);
+ va_end(ap);
+ fflush(debug_file);
+}
+void log_msg(const char *fmt,...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ do_log(LOG_MSG, fmt, ap);
+ va_end(ap);
+}
+
+void log_emerg(const char *fmt, ...)
+{
+ if (emerg_file) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(emerg_file, fmt, ap);
+ va_end(ap);
+ fflush(emerg_file);
+ }
+}
+
+void log_free_msg(struct log_msg *m)
+{
+ struct _log_msg *msg = (struct _log_msg *)m->lpd;
+
+ //printf("free msg %p\n", m);
+
+ rte_free(m->hdr);
+ _log_free_msg(msg);
+
+ rte_free(m);
+}
+
+
+static void _log_free_msg(struct _log_msg *msg)
+{
+ struct log_chunk *chunk;
+
+ if (__sync_sub_and_fetch(&msg->refs, 1))
+ return;
+
+ while(!list_empty(&msg->chunks)) {
+ chunk = list_entry(msg->chunks.next, typeof(*chunk), entry);
+ list_del(&chunk->entry);
+ rte_free(chunk);
+ }
+
+ rte_free(msg);
+}
+
+static struct log_msg *clone_msg(struct _log_msg *msg)
+{
+ struct log_msg *m = rte_malloc(NULL, sizeof(*m), 0);
+ if (!m) {
+ log_emerg("log: out of memory\n");
+ return NULL;
+ }
+
+ m->hdr = rte_malloc(NULL, sizeof(*m->hdr), 0);
+ if (!m->hdr) {
+ log_emerg("log: out of memory\n");
+ rte_free(m);
+ return NULL;
+ }
+
+ m->hdr->len = 0;
+ m->lpd = msg;
+ m->chunks = &msg->chunks;
+ m->timestamp = msg->timestamp;
+ m->level = msg->level;
+
+ __sync_add_and_fetch(&msg->refs, 1);
+
+ //printf("clone msg %p\n", m);
+ return m;
+}
+
+static int add_msg(struct _log_msg *msg, const char *buf, int len)
+{
+ struct log_chunk *chunk;
+ int i, chunk_cnt, n;
+
+ if (!list_empty(&msg->chunks)) {
+ chunk = list_entry(msg->chunks.prev, typeof(*chunk), entry);
+ if (chunk->len != LOG_CHUNK_SIZE) {
+ n = LOG_CHUNK_SIZE - chunk->len;
+ if (n > len)
+ n = len;
+ memcpy(chunk->msg + chunk->len, buf, n);
+ chunk->len += n;
+ chunk->msg[chunk->len] = 0;
+ buf += n;
+ len -= n;
+ if (len == 0)
+ return 0;
+ }
+ }
+
+ chunk_cnt = (len - 1)/LOG_CHUNK_SIZE + 1;
+
+ for (i = 0; i < chunk_cnt; i++) {
+ chunk = rte_malloc(NULL, sizeof(*chunk), 0);
+ if (!chunk)
+ return -1;
+
+ chunk->len = i == chunk_cnt -1 ? len - i * LOG_CHUNK_SIZE : LOG_CHUNK_SIZE;
+ memcpy(chunk->msg, buf + i * LOG_CHUNK_SIZE, chunk->len);
+ chunk->msg[chunk->len] = 0;
+
+ list_add_tail(&chunk->entry, &msg->chunks);
+ }
+
+ return 0;
+}
+
+static void write_msg(FILE *f, struct _log_msg *msg)
+{
+ struct log_chunk *chunk;
+
+ fprintf(f, "[%u.%03u] ", (unsigned)msg->timestamp.tv_sec, (unsigned)msg->timestamp.tv_usec/1000);
+
+ list_for_each_entry(chunk, &msg->chunks, entry)
+ fwrite(chunk->msg, chunk->len, 1, f);
+
+ fflush(f);
+}
+
+void log_register_target(struct log_target *t)
+{
+ list_add_tail(&t->entry, &targets);
+}
+
+static void sighup(int n)
+{
+ struct log_target *t;
+
+ list_for_each_entry(t, &targets, entry)
+ if (t->reopen)
+ t->reopen();
+}
+
+static void config_load(void)
+{
+ const char *opt;
+
+ opt = conf_get_opt("log", "level");
+ if (opt && atoi(opt) >= 0)
+ log_level = atoi(opt);
+
+ opt = conf_get_opt("log", "log-emerg");
+ if (opt) {
+ if (emerg_file)
+ emerg_file = freopen(opt, "a", emerg_file);
+ else
+ emerg_file = fopen(opt, "a");
+ if (!emerg_file)
+ fprintf(stderr, "log:open: %s\n", strerror(errno));
+ } else if (emerg_file) {
+ fclose(emerg_file);
+ emerg_file = NULL;
+ }
+
+ opt = conf_get_opt("log", "log-debug");
+ if (opt) {
+ if (debug_file)
+ debug_file = freopen(opt, "a", debug_file);
+ else
+ debug_file = fopen(opt, "a");
+ if (!debug_file)
+ fprintf(stderr, "log:open: %s\n", strerror(errno));
+ } else if (debug_file) {
+ fclose(debug_file);
+ debug_file = NULL;
+ }
+}
+
+static void log_init(void)
+{
+ pthread_key_create(&pth_key, stat_buf_free);
+
+ config_load();
+
+ signal(SIGHUP, sighup);
+}
+
+DEFINE_INIT(0, log_init);
+
diff --git a/accel-dp/log.h b/accel-dp/log.h
new file mode 100644
index 0000000..2f4d1b8
--- /dev/null
+++ b/accel-dp/log.h
@@ -0,0 +1,61 @@
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#ifdef MINIMAL
+#define log_error(...) fprintf(stderr, __VA_ARGS__)
+#define log_warn(...) fprintf(stderr, __VA_ARGS__)
+#define log_info1(...) fprintf(stderr, __VA_ARGS__)
+#define log_info2(...) fprintf(stderr, __VA_ARGS__)
+#define log_debug(...) fprintf(stderr, __VA_ARGS__)
+#define log_msg(...) fprintf(stderr, __VA_ARGS__)
+#define log_append(...) fprintf(stderr, __VA_ARGS__)
+#define log_emerg(...) fprintf(stderr, __VA_ARGS__)
+#else
+
+#include <stdarg.h>
+#include <sys/time.h>
+#include "list.h"
+
+#define LOG_MAX_SIZE 4096
+#define LOG_CHUNK_SIZE 128
+
+struct log_msg {
+ struct list_head entry;
+ struct timeval timestamp;
+ void *lpd;
+ int level;
+ struct log_chunk *hdr;
+ struct list_head *chunks;
+};
+
+struct log_chunk {
+ struct list_head entry;
+ int len;
+ char msg[0];
+};
+
+struct log_target {
+ struct list_head entry;
+
+ void (*log)(struct log_msg *);
+ void (*reopen)(void);
+};
+
+void log_free_msg(struct log_msg *msg);
+
+void log_emerg(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+
+void log_error(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_warn(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_info1(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_info2(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_debug(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_msg(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
+void log_append(const char *str, int len);
+
+#define log_ppp_error(...) log_error(__VA_ARGS__)
+
+void log_register_target(struct log_target *t);
+#endif
+
+#endif
diff --git a/accel-dp/log_file.c b/accel-dp/log_file.c
new file mode 100644
index 0000000..395e24c
--- /dev/null
+++ b/accel-dp/log_file.c
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <aio.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include "init.h"
+#include "common.h"
+#include "conf_file.h"
+
+#include "log.h"
+
+//static const char* level_name[]={" msg", "error", " warn", " info", " info", "debug"};
+static int log_fd = -1;
+static int conf_buf_size;
+
+#define THREADED_LOG_FILE
+
+#ifdef THREADED_LOG_FILE
+static LIST_HEAD(log_queue);
+static LIST_HEAD(log_buf);
+static int buf_size;
+static int buf_cnt;
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond;
+static pthread_t thr;
+static int need_reopen;
+#endif
+
+static void make_hdr(struct log_msg *msg)
+{
+ struct tm tm;
+
+ tm = *localtime(&msg->timestamp.tv_sec);
+
+ msg->hdr->len = sprintf(msg->hdr->msg, "[%i-%02i-%02i %02i:%02i:%02i]: ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec/*, (int)msg->timestamp.tv_usec/100000*/);
+}
+
+/*static void __log(struct log_msg *msg)
+{
+ struct log_chunk *chunk;
+ struct iovec iov[IOV_MAX];
+ int iov_cnt;
+ struct list_head *pos = msg->chunks->next;
+
+ make_hdr(msg);
+
+ iov[0].iov_base = msg->hdr->msg;
+ iov[0].iov_len = msg->hdr->len;
+ iov_cnt = 1;
+
+ while (pos != msg->chunks) {
+ chunk = list_entry(pos, typeof(*chunk), entry);
+ iov[iov_cnt].iov_base = chunk->msg;
+ iov[iov_cnt].iov_len = chunk->len;
+ iov_cnt++;
+ pos = pos->next;
+
+ if (iov_cnt == IOV_MAX || pos == msg->chunks) {
+ writev(log_fd, iov, iov_cnt);
+ iov_cnt = 0;
+ }
+ }
+
+ log_free_msg(msg);
+}*/
+
+static void write_buf()
+{
+ struct log_msg *msg;
+ struct log_chunk *chunk;
+ struct iovec iov[IOV_MAX];
+ int n = 0;
+
+ list_for_each_entry(msg, &log_buf, entry) {
+ iov[n].iov_base = msg->hdr->msg;
+ iov[n].iov_len = msg->hdr->len;
+ n++;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ iov[n].iov_base = chunk->msg;
+ iov[n].iov_len = chunk->len;
+ n++;
+
+ if (n >= IOV_MAX - 2) {
+ writev(log_fd, iov, n);
+ n = 0;
+ }
+ }
+ }
+
+ if (n)
+ writev(log_fd, iov, n);
+
+ while (!list_empty(&log_buf)) {
+ msg = list_entry(log_buf.next, typeof(*msg), entry);
+ list_del(&msg->entry);
+ log_free_msg(msg);
+ }
+
+ buf_size = 0;
+ buf_cnt = 0;
+}
+
+static void do_log(struct log_msg *msg)
+{
+#ifndef THREADED_LOG_FILE
+ struct log_chunk *chunk;
+#endif
+
+ if (log_fd < 0 || msg->level == 5) {
+ log_free_msg(msg);
+ return;
+ }
+
+ make_hdr(msg);
+
+#ifdef THREADED_LOG_FILE
+ pthread_mutex_lock(&lock);
+ list_add_tail(&msg->entry, &log_queue);
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&lock);
+#else
+ buf_cnt++;
+ buf_size += msg->hdr->len;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ buf_size += chunk->len;
+ buf_cnt++;
+ }
+
+ if (buf_cnt > IOV_MAX - 16 || buf_size >= conf_buf_size)
+ write_buf();
+#endif
+}
+
+static void __reopen(void)
+{
+ const char *fname = conf_get_opt("log", "log-file");
+
+ if (log_fd >= 0) {
+ close(log_fd);
+ log_fd = -1;
+ }
+
+ if (!fname)
+ return;
+
+ log_fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+ if (log_fd < 0) {
+ log_emerg("log_file: open '%s': %s\n", fname, strerror(errno));
+ return;
+ }
+
+ fcntl(log_fd, F_SETFD, FD_CLOEXEC);
+}
+
+static void reopen(void)
+{
+#ifdef THREADED_LOG_FILE
+ pthread_mutex_lock(&lock);
+ need_reopen = 1;
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&lock);
+#else
+ __reopen();
+#endif
+}
+
+#ifdef THREADED_LOG_FILE
+static void *log_thread(void *ignored)
+{
+ struct log_msg *msg;
+ struct log_chunk *chunk;
+
+ pthread_mutex_lock(&lock);
+ while (1) {
+ if (need_reopen) {
+ need_reopen = 0;
+ __reopen();
+ }
+ while (!list_empty(&log_queue)) {
+ msg = list_entry(log_queue.next, typeof(*msg), entry);
+ list_move_tail(&msg->entry, &log_buf);
+
+ buf_cnt++;
+ buf_size += msg->hdr->len;
+
+ list_for_each_entry(chunk, msg->chunks, entry) {
+ buf_size += chunk->len;
+ buf_cnt++;
+ }
+
+ if (buf_cnt > IOV_MAX - 16 || buf_size >= conf_buf_size) {
+ pthread_mutex_unlock(&lock);
+ write_buf();
+ pthread_mutex_lock(&lock);
+ }
+ }
+ pthread_cond_wait(&cond, &lock);
+ }
+ pthread_mutex_unlock(&lock);
+
+ return NULL;
+}
+#endif
+
+static struct log_target target = {
+ .log = do_log,
+ .reopen = reopen,
+};
+
+static void load_config()
+{
+ const char *opt = conf_get_opt("log", "buffer");
+ if (opt)
+ conf_buf_size = atoi(opt);
+ else
+ conf_buf_size = 0;
+}
+
+static void init(void)
+{
+ if (!conf_get_opt("log", "log-file"))
+ return;
+
+ load_config();
+
+ log_register_target(&target);
+ reopen();
+
+#ifdef THREADED_LOG_FILE
+ pthread_cond_init(&cond, NULL);
+ pthread_create(&thr, NULL, log_thread, NULL);
+#endif
+}
+
+DEFINE_INIT(2, init);
diff --git a/accel-dp/main.c b/accel-dp/main.c
new file mode 100644
index 0000000..bdf8163
--- /dev/null
+++ b/accel-dp/main.c
@@ -0,0 +1,378 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+
+#include <rte_config.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_errno.h>
+#include <rte_debug.h>
+
+#include "init.h"
+#include "conf_file.h"
+#include "event.h"
+
+#define RTE_LOGTYPE_INIT RTE_LOGTYPE_USER1
+#define MBUF_CACHE_SIZE 128
+
+int sock_fd;
+
+static struct rte_mempool *mbuf_pool;
+
+static LIST_HEAD(init_list);
+
+struct init {
+ struct list_head entry;
+
+ int order;
+ void (*func)(void);
+};
+
+void register_init(int order, void (*func)(void))
+{
+ struct init *i1, *i = malloc(sizeof(*i));
+ struct list_head *p = init_list.next;
+
+ i->order = order;
+ i->func = func;
+
+ while (p != &init_list) {
+ i1 = list_entry(p, typeof(*i1), entry);
+ if (order < i1->order)
+ break;
+ p = p->next;
+ }
+ list_add_tail(&i->entry, p);
+}
+
+static void run_init(void)
+{
+ struct init *i;
+
+ list_for_each_entry(i, &init_list, entry)
+ i->func();
+}
+
+static void change_limits(void)
+{
+ FILE *f;
+ struct rlimit lim;
+ unsigned int nr_open = 1024*1024;
+
+ f = fopen("/proc/sys/fs/nr_open", "r");
+ if (f) {
+ fscanf(f, "%d", &nr_open);
+ fclose(f);
+ }
+
+ lim.rlim_cur = nr_open;
+ lim.rlim_max = nr_open;
+ setrlimit(RLIMIT_NOFILE, &lim);
+}
+
+static int bind_driver(const char *opt, char **val)
+{
+ char *ptr = strchr(opt, ':');
+ char drv[128];
+ int fd, r;
+ char fname[1024];
+ char bus_id[64];
+ struct stat st;
+ char vendor[16], device[16];
+
+ if (!ptr)
+ return -1;
+
+ if (strchr(ptr + 1, ':')) {
+ memcpy(drv, opt, ptr - opt);
+ drv[ptr - opt] = 0;
+ opt = ptr + 1;
+ } else
+ strcpy(drv, "uio_pci_generic");
+
+ sprintf(bus_id, "0000:%s", opt);
+
+ sprintf(fname, "/sys/bus/pci/devices/%s", bus_id);
+ if (stat(fname, &st)) {
+ fprintf(stderr, "%s: device not found\n", opt);
+ return -1;
+ }
+
+ sprintf(fname, "/sys/bus/pci/devices/%s/vendor", bus_id);
+ fd = open(fname, O_RDONLY);
+ r = read(fd, vendor, sizeof(vendor));
+ if (r <= 0) {
+ fprintf(stderr, "%s: failed to read vendor\n", opt);
+ close(fd);
+ return -1;
+ }
+ vendor[r - 1] = 0;
+ close(fd);
+
+ sprintf(fname, "/sys/bus/pci/devices/%s/device", bus_id);
+ fd = open(fname, O_RDONLY);
+ r = read(fd, device, sizeof(device));
+ if (r <= 0) {
+ fprintf(stderr, "%s: failed to read device\n", opt);
+ close(fd);
+ return -1;
+ }
+ device[r - 1] = 0;
+ close(fd);
+
+ sprintf(fname, "modprobe -q %s", drv);
+ system(fname);
+
+ sprintf(fname, "/sys/bus/pci/drivers/%s", drv);
+ if (stat(fname, &st)) {
+ fprintf(stderr, "%s: driver '%s' is not loaded\n", opt, drv);
+ return -1;
+ }
+
+ sprintf(fname, "/sys/bus/pci/devices/%s/driver", bus_id);
+
+ r = readlink(fname, fname, sizeof(fname));
+ if (r > 0) {
+ fname[r] = 0;
+ ptr = fname + r - 1;
+ while (*ptr != '/')
+ ptr--;
+
+ if (strcmp(ptr + 1, drv)) {
+ fprintf(stderr, "%s: unbind driver: %s\n", opt, ptr + 1);
+
+ sprintf(fname, "/sys/bus/pci/devices/%s/driver/unbind", bus_id);
+
+ fd = open(fname, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: failed to unbind driver: %s\n", opt, strerror(errno));
+ return -1;
+ }
+
+ if (write(fd, bus_id, strlen(bus_id)) < 0) {
+ fprintf(stderr, "%s: failed to unbind driver: %s\n", opt, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ } else
+ goto out;
+ }
+
+ sprintf(fname, "/sys/bus/pci/drivers/%s/new_id", drv);
+ fd = open(fname, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: failed to bind driver %s: %s\n", opt, drv, strerror(errno));
+ return -1;
+ }
+
+ sprintf(fname, "%s %s", vendor, device);
+ if (write(fd, fname, strlen(fname)) < 0) {
+ fprintf(stderr, "%s: failed to bind driver %s: %s\n", opt, drv, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ /*sprintf(fname, "/sys/bus/pci/drivers/%s/bind", drv);
+ fd = open(fname, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: failed to bind driver %s: %s\n", opt, drv, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if (write(fd, bus_id, strlen(bus_id)) < 0) {
+ fprintf(stderr, "%s: failed to bind driver %s: %s\n", opt, drv, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);*/
+
+out:
+ *val = (char *)opt;
+ return 0;
+}
+
+static int build_rte_args(char **argv)
+{
+ int i = 0;
+ struct conf_sect *s = conf_get_sect("core");
+ struct conf_opt *opt;
+
+ if (!s)
+ return 0;
+
+ for (opt = s->opt; opt; opt = opt->next) {
+ if (!strcmp(opt->name, "coremask")) {
+ argv[i++] = "-c";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "corelist")) {
+ argv[i++] = "-l";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "coremap")) {
+ argv[i++] = "--lcores";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "master-lcore")) {
+ argv[i++] = "--master-lcore";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "mem-channels")) {
+ argv[i++] = "-n";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "mem-ranks")) {
+ argv[i++] = "-r";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "socket-mem")) {
+ argv[i++] = "-m";
+ argv[i++] = opt->val;
+ } else if (!strcmp(opt->name, "huge-dir")) {
+ argv[i++] = "--huge-dir";
+ argv[i++] = opt->val;
+ }
+ }
+
+ s = conf_get_sect("interface");
+
+ for (opt = s->opt; opt; opt = opt->next) {
+ const char *busid = conf_get_subopt(opt, "busid");
+ if (!busid) {
+ fprintf(stderr, "%s: busid not specified\n", opt->name);
+ return -1;
+ }
+
+ if (strcmp(busid, "kni")) {
+ if (bind_driver(busid, &argv[i + 1]))
+ return -1;
+ argv[i++] = "-w";
+ i++;
+ }
+ }
+
+ return i;
+}
+
+static int init_pktmbuf_pool()
+{
+ int mbuf_cnt = 16*1024;
+ const char *opt = conf_get_opt("core", "mbuf-count");
+
+ if (opt)
+ mbuf_cnt = atoi(opt);
+
+ mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", mbuf_cnt, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ if (!mbuf_pool) {
+ fprintf(stderr, "%s\n", rte_strerror(rte_errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned lcore_id;
+ int i;
+ char *cf = NULL;
+ char *pid_file = NULL;
+ int goto_daemon = 0;
+ int rte_argc;
+ char *rte_argv[256];
+ const char *opt;
+ int dist_lcore;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-c") && i + 1 < argc)
+ cf = argv[++i];
+ else if (!strcmp(argv[i], "-p") && i + 1 < argc)
+ pid_file = argv[++i];
+ else if (!strcmp(argv[i], "-d"))
+ goto_daemon = 1;
+ }
+
+ if (!cf) {
+ printf("usage: accel-dpdk [-d] [-p <pid file>] -c <config file>\n");
+ return 1;
+ }
+
+ if (conf_load(cf))
+ return 1;
+
+ rte_argv[0] = argv[0];
+ rte_argc = build_rte_args(rte_argv + 1) + 1;
+ if (rte_argc == 0)
+ return 1;
+
+ if (rte_eal_init(rte_argc, rte_argv) < 0) {
+ fprintf(stderr, "Cannot init EAL\n");
+ return 1;
+ }
+
+ if (init_pktmbuf_pool())
+ return -1;
+
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ run_init();
+
+ if (ctrl_init())
+ return 1;
+
+ if (eth_dev_init(mbuf_pool))
+ return -1;
+
+ if (kni_dev_init(mbuf_pool))
+ return -1;
+
+ opt = conf_get_opt("core", "distributor-lcore");
+ if (opt)
+ dist_lcore = atoi(opt);
+ else
+ dist_lcore = -1;
+
+ if (distributor_init(dist_lcore != -1))
+ return -1;
+
+ if (goto_daemon)
+ daemon(0, 0);
+
+ change_limits();
+
+ if (pid_file) {
+ FILE *f = fopen(pid_file, "w");
+ if (f) {
+ fprintf(f, "%i", getpid());
+ fclose(f);
+ }
+ }
+
+ /* call lcore_hello() on every slave lcore */
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ printf("%i\n", lcore_id);
+ if (lcore_id == dist_lcore)
+ rte_eal_remote_launch(lcore_distributor, NULL, lcore_id);
+ else
+ rte_eal_remote_launch(lcore_worker, NULL, lcore_id);
+ }
+
+ if (dist_lcore == -1)
+ distributor_loop(1);
+ else
+ event_loop();
+
+ rte_eal_mp_wait_lcore();
+ return 0;
+}
diff --git a/accel-dp/sock.h b/accel-dp/sock.h
new file mode 100644
index 0000000..0bff811
--- /dev/null
+++ b/accel-dp/sock.h
@@ -0,0 +1,40 @@
+#ifndef __SOCK_H
+#define __SOCK_H
+
+#include "event.h"
+
+#define SOCK_BUF_SIZE 1024
+
+#define PF_PPP 255
+
+struct sock;
+
+struct proto_ops {
+ int (*socket)(struct sock *sk, int type, int proto);
+ int (*bind)(struct sock *sk, const struct sockaddr *addr, socklen_t addrlen);
+ int (*listen)(struct sock *sk, int backlog);
+ int (*connect)(struct sock *sk, const struct sockaddr *addr, socklen_t addrlen);
+ int (*recv)(struct sock *sk, size_t len, int flags, socklen_t addrlen);
+ int (*send)(struct sock *sk, void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen);
+ int (*ioctl)(struct sock *sk, unsigned long request, void *arg);
+ void (*close)(struct sock *sk);
+};
+
+struct msg_result;
+
+struct sock {
+ struct event_handler hnd;
+ void *priv;
+ struct msg_result *res;
+ const struct proto_ops *ops;
+};
+
+int sock_errno(struct sock *sk, int err);
+
+int sock_no_listen(struct sock *sk, int backlog);
+int sock_no_connect(struct sock *sk, const struct sockaddr *addr, socklen_t addrlen);
+int sock_no_ioctl(struct sock *sk, unsigned long request, void *arg);
+
+void sock_register_proto(int domain, int type, int proto, const struct proto_ops *ops);
+
+#endif