summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2015-11-23 00:02:23 +0300
committerDmitry Kozlov <xeb@mail.ru>2015-12-04 21:30:40 +0300
commit2dbcda2be5cbc221a827d0559da53aa4333a6d56 (patch)
treee4616c1220da771a71af56d41e142e53a8258e27
parent43a2c73a9607561faa30ab6cd9812cbfb361a9c1 (diff)
downloadaccel-ppp-2dbcda2be5cbc221a827d0559da53aa4333a6d56.tar.gz
accel-ppp-2dbcda2be5cbc221a827d0559da53aa4333a6d56.zip
implemented module for accel-dpdk daemon interfacing
-rw-r--r--accel-pppd/CMakeLists.txt2
-rw-r--r--accel-pppd/net/CMakeLists.txt7
-rw-r--r--accel-pppd/net/dpdk.c486
-rw-r--r--accel-pppd/net/if_dpdk.h67
4 files changed, 562 insertions, 0 deletions
diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt
index 314a9f8b..ff2cfe0e 100644
--- a/accel-pppd/CMakeLists.txt
+++ b/accel-pppd/CMakeLists.txt
@@ -47,6 +47,8 @@ IF (SHAPER)
ADD_SUBDIRECTORY(shaper)
ENDIF (SHAPER)
+ADD_SUBDIRECTORY(net)
+
INCLUDE(CheckIncludeFile)
CHECK_INCLUDE_FILE("linux/netfilter/ipset/ip_set.h" HAVE_IPSET)
diff --git a/accel-pppd/net/CMakeLists.txt b/accel-pppd/net/CMakeLists.txt
new file mode 100644
index 00000000..db3aca3e
--- /dev/null
+++ b/accel-pppd/net/CMakeLists.txt
@@ -0,0 +1,7 @@
+IF (DEFINED DPDK)
+ ADD_LIBRARY(net-dpdk SHARED dpdk.c)
+
+ INSTALL(TARGETS net-dpdk
+ LIBRARY DESTINATION lib${LIB_SUFFIX}/accel-ppp
+ )
+ENDIF()
diff --git a/accel-pppd/net/dpdk.c b/accel-pppd/net/dpdk.c
new file mode 100644
index 00000000..cfd64bad
--- /dev/null
+++ b/accel-pppd/net/dpdk.c
@@ -0,0 +1,486 @@
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <linux/ppp-ioctl.h>
+#include <linux/if.h>
+
+#include "triton.h"
+#include "ap_session.h"
+#include "log.h"
+
+#include "if_dpdk.h"
+
+static struct sockaddr_un dpdk_addr;
+static int dpdk_sock;
+
+static int dpdk_socket(int domain, int type, int proto)
+{
+ struct msg_socket msg = {
+ .id = MSG_SOCKET,
+ .domain = domain,
+ .type = type,
+ .proto = proto,
+ };
+ struct msg_result res;
+
+ int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0)
+ return -1;
+
+ if (connect(sock, (struct sockaddr *)&dpdk_addr, sizeof(dpdk_addr))) {
+ close(sock);
+ return -1;
+ }
+
+ if (write(sock, &msg, sizeof(msg)) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ close(sock);
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ close(sock);
+ errno = res.err;
+ return -1;
+ }
+
+ return sock;
+}
+
+static int dpdk_connect(int sock, const struct sockaddr *addr, socklen_t len)
+{
+ struct msg_connect msg = {
+ .id = MSG_CONNECT,
+ .addrlen = len,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = (void *)addr,
+ .iov_len = len,
+ }
+ };
+
+ if (writev(sock, iov, 2) < 0)
+ return -1;
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int dpdk_bind(int sock, const struct sockaddr *addr, socklen_t len)
+{
+ struct msg_bind msg = {
+ .id = MSG_BIND,
+ .addrlen = len,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = (void *)addr,
+ .iov_len = len,
+ }
+ };
+
+ if (writev(sock, iov, 2) < 0)
+ return -1;
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int dpdk_listen(int sock, int backlog)
+{
+ struct msg_listen msg = {
+ .id = MSG_LISTEN,
+ .backlog = backlog,
+ };
+ struct msg_result res;
+
+ if (write(sock, &msg, sizeof(msg)) < 0)
+ return -1;
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return 0;
+}
+
+static ssize_t dpdk_recv(int sock, void *buf, size_t len, int flags)
+{
+ struct msg_recv msg = {
+ .id = MSG_RECV,
+ .len = len,
+ .flags = flags,
+ .addrlen = 0,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &res,
+ .iov_len = sizeof(res),
+ },
+ {
+ .iov_base = buf,
+ .iov_len = len,
+ }
+ };
+
+ if (write(sock, &msg, sizeof(msg)))
+ return -1;
+
+again:
+ if (readv(sock, iov, 2) < sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ if (!res.len)
+ goto again;
+
+ return res.len;
+}
+
+static ssize_t dpdk_recvfrom(int sock, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ struct msg_recv msg = {
+ .id = MSG_RECV,
+ .len = len,
+ .flags = flags,
+ .addrlen = 0,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &res,
+ .iov_len = sizeof(res),
+ },
+ {
+ .iov_base = buf,
+ .iov_len = len,
+ }
+ };
+
+ if (write(sock, &msg, sizeof(msg)))
+ return -1;
+
+again:
+ if (readv(sock, iov, 2) < sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ if (!res.len)
+ goto again;
+
+ memcpy(src_addr, &res.ss, res.addrlen);
+ *addrlen = res.addrlen;
+
+ return res.len;
+}
+
+static ssize_t dpdk_send(int sock, const void *buf, size_t len, int flags)
+{
+ struct msg_send msg = {
+ .id = MSG_SEND,
+ .len = len,
+ .flags = flags,
+ .addrlen = 0,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = (void *)buf,
+ .iov_len = len,
+ }
+ };
+
+ if (writev(sock, iov, 2) < 0)
+ return -1;
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return res.len;
+}
+
+static ssize_t dpdk_sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+ struct msg_send msg = {
+ .id = MSG_SEND,
+ .len = len,
+ .flags = flags,
+ .addrlen = addrlen,
+ };
+ struct msg_result res;
+ struct iovec iov[3] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = (void *)dest_addr,
+ .iov_len = addrlen,
+ },
+ {
+ .iov_base = (void *)buf,
+ .iov_len = len,
+ }
+ };
+
+ if (writev(sock, iov, 3) < 0)
+ return -1;
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return res.len;
+}
+
+static int dpdk_set_nonblocking(int sock, int f)
+{
+ return 0;
+}
+
+static int dpdk_ppp_open()
+{
+ int id = MSG_PPP_OPEN;
+ struct msg_result res;
+ int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+
+ if (sock < 0)
+ return -1;
+
+ if (connect(sock, (struct sockaddr *)&dpdk_addr, sizeof(dpdk_addr))) {
+ close(sock);
+ return -1;
+ }
+
+ if (write(sock, &id, sizeof(id)) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ if (read(sock, &res, sizeof(res)) != sizeof(res)) {
+ close(sock);
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ close(sock);
+ errno = res.err;
+ return -1;
+ }
+
+ return sock;
+}
+
+static int dpdk_ppp_ioctl(int fd, unsigned long request, void *arg)
+{
+ struct msg_ioctl msg = {
+ .id = MSG_PPP_IOCTL,
+ .request = request,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = arg,
+ }
+ };
+
+ switch (request) {
+ case PPPIOCSNPMODE:
+ iov[1].iov_len = sizeof(struct npioctl);
+ break;
+ case PPPIOCSCOMPRESS:
+ iov[1].iov_len = sizeof(struct ppp_option_data);
+ break;
+ case PPPIOCGFLAGS:
+ case PPPIOCGCHAN:
+ case PPPIOCNEWUNIT:
+ iov[1].iov_len = 0;
+ break;
+ case PPPIOCSFLAGS:
+ case PPPIOCSMRU:
+ case PPPIOCATTCHAN:
+ case PPPIOCCONNECT:
+ iov[1].iov_len = sizeof(int);
+ break;
+
+ }
+
+ if (writev(fd, iov, iov[1].iov_len ? 2 : 1) < 0)
+ return -1;
+
+ iov[0].iov_base = &res;
+ iov[0].iov_len = sizeof(res);
+ iov[1].iov_base = arg;
+ iov[1].iov_len = 1024;
+
+ if (readv(fd, iov, 2) < sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return res.len;
+}
+
+static int dpdk_sock_ioctl(unsigned long request, void *arg)
+{
+ struct msg_ioctl msg = {
+ .id = MSG_SOCK_IOCTL,
+ .request = request,
+ };
+ struct msg_result res;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof(msg),
+ },
+ {
+ .iov_base = arg,
+ .iov_len = sizeof(struct ifreq),
+ }
+ };
+
+ if (writev(dpdk_sock, iov, 2) < 0)
+ return -1;
+
+ iov[0].iov_base = &res;
+ iov[0].iov_len = sizeof(res);
+
+ if (readv(dpdk_sock, iov, 2) < sizeof(res)) {
+ errno = EBADE;
+ return -1;
+ }
+
+ if (res.err) {
+ errno = res.err;
+ return -1;
+ }
+
+ return res.len;
+}
+
+static const struct ap_net dpdk_net = {
+ .socket = dpdk_socket,
+ .connect = dpdk_connect,
+ .bind = dpdk_bind,
+ .listen = dpdk_listen,
+ .recv = dpdk_recv,
+ .recvfrom = dpdk_recvfrom,
+ .send = dpdk_send,
+ .sendto = dpdk_sendto,
+ .set_nonblocking = dpdk_set_nonblocking,
+ .ppp_open = dpdk_ppp_open,
+ .ppp_ioctl = dpdk_ppp_ioctl,
+ .sock_ioctl = dpdk_sock_ioctl,
+};
+
+static void init()
+{
+ const char *opt = conf_get_opt("net-dpdk", "socket");
+
+ if (!opt)
+ return;
+
+ if (strlen(opt) >= sizeof(dpdk_addr.sun_path)) {
+ log_error("net-dpdk: socket path is too long\n");
+ return;
+ }
+
+ strcpy(dpdk_addr.sun_path, opt);
+
+ dpdk_addr.sun_family = AF_UNIX;
+
+ dpdk_sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (dpdk_sock < 0)
+ return;
+
+ if (connect(dpdk_sock, (struct sockaddr *)&dpdk_addr, sizeof(dpdk_addr))) {
+ log_error("dpdk: connect: %s\n", strerror(errno));
+ close(dpdk_sock);
+ return;
+ }
+}
+
+DEFINE_INIT(1, init)
diff --git a/accel-pppd/net/if_dpdk.h b/accel-pppd/net/if_dpdk.h
new file mode 100644
index 00000000..4981dc9b
--- /dev/null
+++ b/accel-pppd/net/if_dpdk.h
@@ -0,0 +1,67 @@
+#ifndef __IF_DPDK_H
+#define __IF_DPDK_H
+
+#define MSG_SOCKET 1
+#define MSG_CONNECT 2
+#define MSG_BIND 3
+#define MSG_LISTEN 4
+#define MSG_RECV 5
+#define MSG_SEND 6
+#define MSG_PPP_OPEN 7
+#define MSG_PPP_IOCTL 8
+#define MSG_SOCK_IOCTL 9
+#define MSG_RESULT 10
+
+struct msg_socket {
+ int id;
+ int domain;
+ int type;
+ int proto;
+};
+
+struct msg_connect {
+ int id;
+ socklen_t addrlen;
+ char addr[0];
+};
+
+struct msg_bind {
+ int id;
+ socklen_t addrlen;
+ char addr[0];
+};
+
+struct msg_listen {
+ int id;
+ int backlog;
+};
+
+struct msg_recv {
+ int id;
+ size_t len;
+ int flags;
+ socklen_t addrlen;
+};
+
+struct msg_send {
+ int id;
+ size_t len;
+ int flags;
+ socklen_t addrlen;
+};
+
+struct msg_ioctl {
+ int id;
+ unsigned long request;
+ char arg[0];
+};
+
+struct msg_result {
+ int err;
+ ssize_t len;
+ socklen_t addrlen;
+ struct sockaddr_storage ss;
+};
+
+#endif
+