Skip to content

Commit

Permalink
Merge pull request torvalds#383 from motomuman/pipe-netfd-network
Browse files Browse the repository at this point in the history
lkl: introduce PIPE network backend for virtio device
  • Loading branch information
thehajime authored Oct 18, 2017
2 parents 4149f70 + db2c3db commit bfb315c
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 19 deletions.
10 changes: 10 additions & 0 deletions tools/lkl/include/lkl.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,16 @@ struct lkl_netdev *lkl_netdev_raw_create(const char *ifname);
*/
struct lkl_netdev *lkl_netdev_macvtap_create(const char *path, int offload);

/**
* lkl_netdev_pipe_create - create pipe net_device for the virtio
* net backend
*
* @ifname - a file name for the rx and tx pipe device. need to be configured
* on host in advance. delimiter is "|". e.g. "rx_name|tx_name".
* @offload - offload bits for the device
*/
struct lkl_netdev *lkl_netdev_pipe_create(char *ifname, int offload);

/*
* lkl_register_dbg_handler- register a signal handler that loads a debug lib.
*
Expand Down
1 change: 1 addition & 0 deletions tools/lkl/lib/Build
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_raw.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_macvtap.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_dpdk.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_vde.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_pipe.o
2 changes: 2 additions & 0 deletions tools/lkl/lib/hijack/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ hijack_init(void)
nd = lkl_netdev_macvtap_create(ifparams, offload);
} else if ((strcmp(iftype, "dpdk") == 0)) {
nd = lkl_netdev_dpdk_create(ifparams, offload, mac);
} else if ((strcmp(iftype, "pipe") == 0)) {
nd = lkl_netdev_pipe_create(ifparams, offload);
} else {
if (offload) {
fprintf(stderr,
Expand Down
32 changes: 19 additions & 13 deletions tools/lkl/lib/virtio_net_fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
struct lkl_netdev_fd {
struct lkl_netdev dev;
/* file-descriptor based device */
int fd;
int fd_rx;
int fd_tx;
/*
* Controlls the poll mask for fd. Can be acccessed concurrently from
* poll, tx, or rx routines but there is no need for syncronization
Expand All @@ -48,7 +49,7 @@ static int fd_net_tx(struct lkl_netdev *nd, struct iovec *iov, int cnt)
container_of(nd, struct lkl_netdev_fd, dev);

do {
ret = writev(nd_fd->fd, iov, cnt);
ret = writev(nd_fd->fd_tx, iov, cnt);
} while (ret == -1 && errno == EINTR);

if (ret < 0) {
Expand All @@ -72,7 +73,7 @@ static int fd_net_rx(struct lkl_netdev *nd, struct iovec *iov, int cnt)
container_of(nd, struct lkl_netdev_fd, dev);

do {
ret = readv(nd_fd->fd, (struct iovec *)iov, cnt);
ret = readv(nd_fd->fd_rx, (struct iovec *)iov, cnt);
} while (ret == -1 && errno == EINTR);

if (ret < 0) {
Expand All @@ -93,9 +94,12 @@ static int fd_net_poll(struct lkl_netdev *nd)
{
struct lkl_netdev_fd *nd_fd =
container_of(nd, struct lkl_netdev_fd, dev);
struct pollfd pfds[2] = {
struct pollfd pfds[3] = {
{
.fd = nd_fd->fd,
.fd = nd_fd->fd_rx,
},
{
.fd = nd_fd->fd_tx,
},
{
.fd = nd_fd->pipe[0],
Expand All @@ -107,21 +111,21 @@ static int fd_net_poll(struct lkl_netdev *nd)
if (nd_fd->poll_rx)
pfds[0].events |= POLLIN|POLLPRI;
if (nd_fd->poll_tx)
pfds[0].events |= POLLOUT;
pfds[1].events |= POLLOUT;

do {
ret = poll(pfds, 2, -1);
ret = poll(pfds, 3, -1);
} while (ret == -1 && errno == EINTR);

if (ret < 0) {
perror("virtio net fd poll");
return 0;
}

if (pfds[1].revents & (POLLHUP|POLLNVAL))
if (pfds[2].revents & (POLLHUP|POLLNVAL))
return LKL_DEV_NET_POLL_HUP;

if (pfds[1].revents & POLLIN) {
if (pfds[2].revents & POLLIN) {
char tmp[PIPE_BUF];

ret = read(nd_fd->pipe[0], tmp, PIPE_BUF);
Expand All @@ -138,7 +142,7 @@ static int fd_net_poll(struct lkl_netdev *nd)
ret |= LKL_DEV_NET_POLL_RX;
}

if (pfds[0].revents & POLLOUT) {
if (pfds[1].revents & POLLOUT) {
nd_fd->poll_tx = 0;
ret |= LKL_DEV_NET_POLL_TX;
}
Expand All @@ -161,7 +165,8 @@ static void fd_net_free(struct lkl_netdev *nd)
struct lkl_netdev_fd *nd_fd =
container_of(nd, struct lkl_netdev_fd, dev);

close(nd_fd->fd);
close(nd_fd->fd_rx);
close(nd_fd->fd_tx);
free(nd_fd);
}

Expand All @@ -173,7 +178,7 @@ struct lkl_dev_net_ops fd_net_ops = {
.free = fd_net_free,
};

struct lkl_netdev *lkl_register_netdev_fd(int fd)
struct lkl_netdev *lkl_register_netdev_fd(int fd_rx, int fd_tx)
{
struct lkl_netdev_fd *nd;

Expand All @@ -186,7 +191,8 @@ struct lkl_netdev *lkl_register_netdev_fd(int fd)

memset(nd, 0, sizeof(*nd));

nd->fd = fd;
nd->fd_rx = fd_rx;
nd->fd_tx = fd_tx;
if (pipe(nd->pipe) < 0) {
perror("pipe");
free(nd);
Expand Down
5 changes: 3 additions & 2 deletions tools/lkl/lib/virtio_net_fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ struct ifreq;
* lkl_register_netdev_linux_fdnet - register a file descriptor-based network
* device as a NIC
*
* @fd - a POSIX file descriptor number for input/output
* @fd_rx - a POSIX file descriptor number for input
* @fd_tx - a POSIX file descriptor number for output
* @returns a struct lkl_netdev_linux_fdnet entry for virtio-net
*/
struct lkl_netdev *lkl_register_netdev_fd(int fd);
struct lkl_netdev *lkl_register_netdev_fd(int fd_rx, int fd_tx);


/**
Expand Down
68 changes: 68 additions & 0 deletions tools/lkl/lib/virtio_net_pipe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* pipe based virtual network interface feature for LKL
* Copyright (c) 2017,2016 Motomu Utsumi
*
* Author: Motomu Utsumi <motomuman@gmail.com>
*
* Current implementation is linux-specific.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

#include "virtio.h"
#include "virtio_net_fd.h"

struct lkl_netdev *lkl_netdev_pipe_create(char *ifname, int offload)
{
struct lkl_netdev *nd;
int fd_rx, fd_tx;
char *ifname_rx = NULL, *ifname_tx = NULL;

ifname_rx = strtok(ifname, "|");
if (ifname_rx == NULL) {
fprintf(stderr, "invalid ifname format: %s\n", ifname);
return NULL;
}

ifname_tx = strtok(NULL, "|");
if (ifname_tx == NULL) {
fprintf(stderr, "invalid ifname format: %s\n", ifname);
return NULL;
}

if (strtok(NULL, "|") != NULL) {
fprintf(stderr, "invalid ifname format: %s\n", ifname);
return NULL;
}

fd_rx = open(ifname_rx, O_RDWR|O_NONBLOCK);
if (fd_rx < 0) {
perror("can not open ifname_rx pipe");
return NULL;
}

fd_tx = open(ifname_tx, O_RDWR|O_NONBLOCK);
if (fd_tx < 0) {
perror("can not open ifname_tx pipe");
close(fd_rx);
return NULL;
}

nd = lkl_register_netdev_fd(fd_rx, fd_tx);
if (!nd) {
perror("failed to register to.");
close(fd_rx);
close(fd_tx);
return NULL;
}

/*
* To avoid mismatch with LKL otherside,
* we always enabled vnet hdr
*/
nd->has_vnet_hdr = 1;
return nd;
}
2 changes: 1 addition & 1 deletion tools/lkl/lib/virtio_net_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ struct lkl_netdev *lkl_netdev_raw_create(const char *ifname)
fd_flags = fcntl(fd, F_GETFD, NULL);
fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);

return lkl_register_netdev_fd(fd);
return lkl_register_netdev_fd(fd, fd);
}
2 changes: 1 addition & 1 deletion tools/lkl/lib/virtio_net_tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct lkl_netdev *lkl_netdev_tap_init(const char *path, int offload,
close(fd);
return NULL;
}
nd = lkl_register_netdev_fd(fd);
nd = lkl_register_netdev_fd(fd, fd);
if (!nd) {
perror("failed to register to.");
close(fd);
Expand Down
65 changes: 65 additions & 0 deletions tools/lkl/tests/hijack-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,71 @@ elif [ "${CROSS_COMPILE}" = "aarch64-linux-android-" ] ; then
(echo "$ans" | grep "100756k") || true
fi

echo "== PIPE tests =="
if [ -z `which mkfifo` ]; then
echo "WARNIG: no mkfifo command, skipping PIPE tests."
else

fifo1=${work_dir}/fifo1
fifo2=${work_dir}/fifo2
mkfifo ${fifo1}
mkfifo ${fifo2}

# Make sure our device has the addresses we expect
addr=$(LKL_HIJACK_NET_IFTYPE=pipe \
LKL_HIJACK_NET_IFPARAMS="${fifo1}|${fifo2}" \
LKL_HIJACK_NET_IP=192.168.13.2 \
LKL_HIJACK_NET_NETMASK_LEN=24 \
LKL_HIJACK_NET_MAC="aa:bb:cc:dd:ee:ff" \
${hijack_script} ip addr)
echo "$addr" | grep eth0
echo "$addr" | grep 192.168.13.2
echo "$addr" | grep "aa:bb:cc:dd:ee:ff"

# Copy ping so we're allowed to run it under LKL
cp $(which ping) .
cp $(which ping6) .

# Ping receiver
LKL_HIJACK_NET_IFTYPE=pipe \
LKL_HIJACK_NET_IFPARAMS="${fifo1}|${fifo2}" \
LKL_HIJACK_NET_IP=192.168.13.1 \
LKL_HIJACK_NET_NETMASK_LEN=24 \
LKL_HIJACK_NET_GATEWAY=192.168.13.2 \
LKL_HIJACK_NET_IPV6=fc03::1 \
LKL_HIJACK_NET_NETMASK6_LEN=64\
LKL_HIJACK_NET_GATEWAY6=fc03::2 \
${hijack_script} sleep 10 &

sleep 5

# Ping under LKL
sudo LKL_HIJACK_NET_IFTYPE=pipe \
LKL_HIJACK_NET_IFPARAMS="${fifo2}|${fifo1}" \
LKL_HIJACK_NET_IP=192.168.13.2 \
LKL_HIJACK_NET_NETMASK_LEN=24 \
LKL_HIJACK_NET_GATEWAY=192.168.13.1 \
LKL_HIJACK_NET_IPV6=fc03::2 \
LKL_HIJACK_NET_NETMASK6_LEN=64\
LKL_HIJACK_NET_GATEWAY6=fc03::1 \
${hijack_script} ./ping 192.168.13.1 -c 1

# Ping 6 under LKL
sudo LKL_HIJACK_NET_IFTYPE=pipe \
LKL_HIJACK_NET_IFPARAMS="${fifo2}|${fifo1}" \
LKL_HIJACK_NET_IP=192.168.13.2 \
LKL_HIJACK_NET_NETMASK_LEN=24 \
LKL_HIJACK_NET_GATEWAY=192.168.13.1 \
LKL_HIJACK_NET_IPV6=fc03::2 \
LKL_HIJACK_NET_NETMASK6_LEN=64\
LKL_HIJACK_NET_GATEWAY6=fc03::1 \
${hijack_script} ./ping6 fc03::1 -c 1

wait
rm ./ping
rm ./ping6
fi

echo "== TAP tests =="
if [ ! -c /dev/net/tun ]; then
echo "WARNING: missing /dev/net/tun, skipping TAP and VDE tests."
Expand Down
2 changes: 2 additions & 0 deletions tools/lkl/tests/net-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ static int test_net_init(int argc, char **argv)
nd = lkl_netdev_raw_create(ifname);
else if (iftype && ifname && (strncmp(iftype, "macvtap", 7) == 0))
nd = lkl_netdev_macvtap_create(ifname, 0);
else if (iftype && ifname && (strncmp(iftype, "pipe", 4) == 0))
nd = lkl_netdev_pipe_create(ifname, 0);

if (!nd) {
fprintf(stderr, "init netdev failed\n");
Expand Down
32 changes: 30 additions & 2 deletions tools/lkl/tests/net.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/bin/bash -e
#!/bin/bash

set -e

# currently not supported mingw
if [ "`printenv CONFIG_AUTO_LKL_POSIX_HOST`" != "y" ] ; then
Expand All @@ -17,15 +19,40 @@ GW=`ip route get ${TEST_HOST} |head -n1 | cut -d ' ' -f3`
script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd)
cd ${script_dir}

# Make a temporary directory to run tests in, since we'll be copying
# things there.
work_dir=$(mktemp -d)

# And make sure we clean up when we're done
function clear_work_dir {
rm -rf ${work_dir}
${SUDO} ip link set dev lkl_ptt1 down &> /dev/null || true
${SUDO} ip tuntap del dev lkl_ptt1 mode tap &> /dev/null || true
${SUDO} ip link del dev lkl_vtap0 type macvtap &> /dev/null || true
}

trap clear_work_dir EXIT

echo "== PIPE (LKL net) tests =="
if [ -z `which mkfifo` ]; then
echo "WARNIG: no mkfifo command, skipping PIPE tests."
else

fifo1=${work_dir}/fifo1
fifo2=${work_dir}/fifo2
mkfifo ${fifo1}
mkfifo ${fifo2}
hijack_script=${script_dir}/../bin/lkl-hijack.sh
LKL_HIJACK_NET_IFTYPE=pipe \
LKL_HIJACK_NET_IFPARAMS="${fifo1}|${fifo2}" \
LKL_HIJACK_NET_IP=192.168.16.1 \
LKL_HIJACK_NET_NETMASK_LEN=24 \
${hijack_script} sleep 10 &
sleep 5
./net-test pipe "${fifo2}|${fifo1}" 192.168.16.1 192.168.16.2 24
wait
fi

echo "== TAP (LKL net) tests =="
if [ -c /dev/net/tun ]; then
${SUDO} ip link set dev lkl_ptt1 down || true
Expand Down Expand Up @@ -56,7 +83,8 @@ if ! [ -z $DST ]; then
${SUDO} ip link set dev ${IFNAME} promisc off

echo "== macvtap (LKL net) tests =="
${SUDO} ip link add link ${IFNAME} name lkl_vtap0 type macvtap mode passthru
${SUDO} ip link add link ${IFNAME} name lkl_vtap0 \
type macvtap mode passthru || true
if ls /dev/tap* > /dev/null 2>&1 ; then
${SUDO} ip link set dev lkl_vtap0 up
${SUDO} chown ${USER} `ls /dev/tap*`
Expand Down

0 comments on commit bfb315c

Please sign in to comment.