diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index 7ea6fd2a3d7e71..50b21a619b6b24 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -301,6 +301,14 @@ struct lkl_netdev *lkl_netdev_dpdk_create(const char *ifname); */ struct lkl_netdev *lkl_netdev_vde_create(const char *switch_path); +/** + * lkl_netdev_raw_create - create raw socket net_device for the virtio net + * backend + * + * @ifname - interface name for the snoop device. + */ +struct lkl_netdev *lkl_netdev_raw_create(const char *ifname); + /* * lkl_register_dbg_handler- register a signal handler that loads a debug lib. * diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index d64bd3c1af36bf..12c3051426fbe7 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -12,6 +12,8 @@ lkl-y += virtio.o lkl-y += dbg.o lkl-y += dbg_handler.o lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net.o +lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_linux_fdnet.o lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_tap.o +lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_raw.o lkl-$(CONFIG_AUTO_LKL_VIRTIO_NET_DPDK) += virtio_net_dpdk.o lkl-$(CONFIG_AUTO_LKL_VIRTIO_NET_VDE) += virtio_net_vde.o diff --git a/tools/lkl/lib/hijack/hijack.c b/tools/lkl/lib/hijack/hijack.c index dd51415ba10636..ae3221797c42f7 100644 --- a/tools/lkl/lib/hijack/hijack.c +++ b/tools/lkl/lib/hijack/hijack.c @@ -158,7 +158,7 @@ HOST_CALL(socket); int socket(int domain, int type, int protocol) { CHECK_HOST_CALL(socket); - if (domain == AF_UNIX) + if (domain == AF_UNIX || domain == PF_PACKET) return host_socket(domain, type, protocol); return lkl_call(__lkl__NR_socket, 3, domain, type, protocol); diff --git a/tools/lkl/lib/hijack/init.c b/tools/lkl/lib/hijack/init.c index 5a87a457802d0e..ea1bf6b869d66c 100644 --- a/tools/lkl/lib/hijack/init.c +++ b/tools/lkl/lib/hijack/init.c @@ -25,7 +25,7 @@ #include #include "xlate.h" -#include "../virtio_net_tap.h" +#include "../virtio_net_linux_fdnet.h" #define __USE_GNU #include @@ -170,11 +170,11 @@ static void mount_cmds_exec(char *_cmds, int (*callback)(char*)) free(cmds); } -void fixup_netdev_tap_ops(void) +void fixup_netdev_linux_fdnet_ops(void) { /* It's okay if this is NULL, because then netdev close will * fall back onto an uncloseable implementation. */ - lkl_netdev_tap_ops.eventfd = dlsym(RTLD_NEXT, "eventfd"); + lkl_netdev_linux_fdnet_ops.eventfd = dlsym(RTLD_NEXT, "eventfd"); } void __attribute__((constructor(102))) @@ -197,7 +197,7 @@ hijack_init(void) char *arp_entries = getenv("LKL_HIJACK_NET_ARP"); /* Must be run before lkl_netdev_tap_create */ - fixup_netdev_tap_ops(); + fixup_netdev_linux_fdnet_ops(); if (tap) { fprintf(stderr, @@ -214,6 +214,8 @@ hijack_init(void) nd = lkl_netdev_dpdk_create(ifparams); else if (strcmp(iftype, "vde") == 0) nd = lkl_netdev_vde_create(ifparams); + else if (strcmp(iftype, "raw") == 0) + nd = lkl_netdev_raw_create(ifparams); } if (nd) { diff --git a/tools/lkl/lib/virtio_net_linux_fdnet.c b/tools/lkl/lib/virtio_net_linux_fdnet.c new file mode 100644 index 00000000000000..7cbe7db2ff182c --- /dev/null +++ b/tools/lkl/lib/virtio_net_linux_fdnet.c @@ -0,0 +1,251 @@ +/* + * Linux File descripter based virtual network interface feature for LKL + * Copyright (c) 2015,2016 Ryo Nakamura, Hajime Tazaki + * + * Author: Ryo Nakamura + * Hajime Tazaki + * Octavian Purdila + * + * Current implementation is linux-specific. + */ + +#include +#include +#include +#include +#include +#include + +#include "virtio.h" +#include "virtio_net_linux_fdnet.h" + +struct lkl_netdev_linux_fdnet_ops lkl_netdev_linux_fdnet_ops = { + /* + * /dev/net/tun is Linux specific so we know our host is some + * flavor of Linux, but this allows graceful support if we're + * on a kernel that's < 2.6.22. + */ + #ifdef __NR_eventfd + /* This sigature was recently (9/2014) changed in glibc. */ + .eventfd = (int (*)(unsigned int, int))eventfd, + #endif /* __NR_eventfd */ +}; + +static int linux_fdnet_net_tx(struct lkl_netdev *nd, void *data, int len) +{ + int ret; + struct lkl_netdev_linux_fdnet *nd_fdnet = + container_of(nd, struct lkl_netdev_linux_fdnet, dev); + + do { + ret = write(nd_fdnet->fd, data, len); + } while (ret == -1 && errno == EINVAL); + if (ret > 0) + return 0; + if (ret < 0 && errno != EAGAIN) + perror("write to Linux fd netdev fails"); + + return -1; +} + +static int linux_fdnet_net_rx(struct lkl_netdev *nd, void *data, int *len) +{ + int ret; + struct lkl_netdev_linux_fdnet *nd_fdnet = + container_of(nd, struct lkl_netdev_linux_fdnet, dev); + + do { + ret = read(nd_fdnet->fd, data, *len); + } while (ret == -1 && errno == EINVAL); + if (ret > 0) { + *len = ret; + return 0; + } + if (ret < 0 && errno != EAGAIN) + perror("read from fdnet device fails"); + + return -1; +} + +static int linux_fdnet_net_poll(struct lkl_netdev *nd, int events) +{ + struct lkl_netdev_linux_fdnet *nd_fdnet = + container_of(nd, struct lkl_netdev_linux_fdnet, dev); + int epoll_fd = -1; + struct epoll_event ev[2]; + int ret; + const int is_rx = events & LKL_DEV_NET_POLL_RX; + const int is_tx = events & LKL_DEV_NET_POLL_TX; + int i; + int ret_ev = 0; + unsigned int event; + + if (is_rx && is_tx) { + fprintf(stderr, "both LKL_DEV_NET_POLL_RX and " + "LKL_DEV_NET_POLL_TX are set\n"); + lkl_host_ops.panic(); + return -1; + } + if (!is_rx && !is_tx) { + fprintf(stderr, "Neither LKL_DEV_NET_POLL_RX nor" + " LKL_DEV_NET_POLL_TX are set.\n"); + lkl_host_ops.panic(); + return -1; + } + + if (is_rx) + epoll_fd = nd_fdnet->epoll_rx_fd; + else if (is_tx) + epoll_fd = nd_fdnet->epoll_tx_fd; + + do { + ret = epoll_wait(epoll_fd, ev, 2, -1); + } while (ret == -1 && errno == EINTR); + if (ret < 0) { + perror("epoll_wait"); + return -1; + } + + for (i = 0; i < ret; ++i) { + if (ev[i].data.fd == nd_fdnet->eventfd) + return -1; + if (ev[i].data.fd == nd_fdnet->fd) { + event = ev[i].events; + if (event & (EPOLLIN | EPOLLPRI)) + ret_ev = LKL_DEV_NET_POLL_RX; + else if (event & EPOLLOUT) + ret_ev = LKL_DEV_NET_POLL_TX; + else + return -1; + } + } + return ret_ev; +} + +static int linux_fdnet_net_close(struct lkl_netdev *nd) +{ + long buf = 1; + struct lkl_netdev_linux_fdnet *nd_fdnet = + container_of(nd, struct lkl_netdev_linux_fdnet, dev); + + if (nd_fdnet->eventfd == -1) { + /* No eventfd support. */ + return 0; + } + + if (write(nd_fdnet->eventfd, &buf, sizeof(buf)) < 0) { + perror("linux-fdnet: failed to close fd"); + /* This should never happen. */ + return -1; + } + + /* The order that we join in doesn't matter. */ + if (lkl_host_ops.thread_join(nd->rx_tid) || + lkl_host_ops.thread_join(nd->tx_tid)) + return -1; + + /* nor does the order that we close */ + if (close(nd_fdnet->fd) || close(nd_fdnet->eventfd) || + close(nd_fdnet->epoll_rx_fd) || close(nd_fdnet->epoll_tx_fd)) { + perror("linux-fdnet net_close fd"); + return -1; + } + + return 0; +} + +struct lkl_dev_net_ops linux_fdnet_net_ops = { + .tx = linux_fdnet_net_tx, + .rx = linux_fdnet_net_rx, + .poll = linux_fdnet_net_poll, + .close = linux_fdnet_net_close, +}; + +static int add_to_epoll(int epoll_fd, int fd, unsigned int events) +{ + struct epoll_event ev; + int ret; + + memset(&ev, 0, sizeof(ev)); + ev.events = events; + ev.data.fd = fd; + ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); + if (ret) { + perror("EPOLL_CTL_ADD fails"); + return -1; + } + return 0; +} + +static int create_epoll_fd(int fd, unsigned int events) +{ + int ret = epoll_create1(0); + + if (ret < 0) { + perror("epoll_create1"); + return -1; + } + if (add_to_epoll(ret, fd, events)) { + close(ret); + return -1; + } + return ret; +} + + +struct lkl_netdev_linux_fdnet *lkl_register_netdev_linux_fdnet(int fd) +{ + struct lkl_netdev_linux_fdnet *nd; + + nd = (struct lkl_netdev_linux_fdnet *) + malloc(sizeof(struct lkl_netdev_linux_fdnet)); + if (!nd) { + fprintf(stderr, "fdnet: failed to allocate memory\n"); + /* TODO: propagate the error state, maybe use errno for that? */ + return NULL; + } + + nd->fd = fd; + /* Making them edge-triggered to save CPU. */ + nd->epoll_rx_fd = create_epoll_fd(nd->fd, EPOLLIN | EPOLLPRI | EPOLLET); + nd->epoll_tx_fd = create_epoll_fd(nd->fd, EPOLLOUT | EPOLLET); + if (nd->epoll_rx_fd < 0 || nd->epoll_tx_fd < 0) { + if (nd->epoll_rx_fd >= 0) + close(nd->epoll_rx_fd); + if (nd->epoll_tx_fd >= 0) + close(nd->epoll_tx_fd); + lkl_unregister_netdev_linux_fdnet(nd); + return NULL; + } + + if (lkl_netdev_linux_fdnet_ops.eventfd) { + /* eventfd is supported by the host, all is well */ + nd->eventfd = lkl_netdev_linux_fdnet_ops.eventfd( + 0, EFD_NONBLOCK | EFD_SEMAPHORE); + + if (nd->eventfd < 0) { + perror("fdnet: create eventfd"); + lkl_unregister_netdev_linux_fdnet(nd); + return NULL; + } + if (add_to_epoll(nd->epoll_rx_fd, nd->eventfd, EPOLLIN) || + add_to_epoll(nd->epoll_tx_fd, nd->eventfd, EPOLLIN)) { + lkl_unregister_netdev_linux_fdnet(nd); + return NULL; + } + } else { + /* no host eventfd support */ + nd->eventfd = -1; + } + + nd->dev.ops = &linux_fdnet_net_ops; + return nd; +} + +void lkl_unregister_netdev_linux_fdnet(struct lkl_netdev_linux_fdnet *nd) +{ + close(nd->eventfd); + close(nd->epoll_rx_fd); + close(nd->epoll_tx_fd); + free(nd); +} diff --git a/tools/lkl/lib/virtio_net_linux_fdnet.h b/tools/lkl/lib/virtio_net_linux_fdnet.h new file mode 100644 index 00000000000000..ba89c6561fca51 --- /dev/null +++ b/tools/lkl/lib/virtio_net_linux_fdnet.h @@ -0,0 +1,41 @@ +#ifndef _VIRTIO_NET_LINUX_FDNET_H +#define _VIRTIO_NET_LINUX_FDNET_H + +struct lkl_netdev_linux_fdnet { + struct lkl_netdev dev; + /* file-descriptor based device */ + int fd; + /* Needed to initiate shutdown */ + int eventfd; + /* epoll fds for rx and tx */ + int epoll_rx_fd; + int epoll_tx_fd; +}; + +extern struct lkl_netdev_linux_fdnet_ops { + /* + * We need this so that we can "unhijack" this function in + * case we decided to hijack it. + */ + int (*eventfd)(unsigned int initval, int flags); +} lkl_netdev_linux_fdnet_ops; + +/** + * lkl_register_netdev_linux_fdnet - register a file descriptor-based network + * device as a NIC + * + * @fd - a POSIX file descriptor number for input/output + * @returns a struct lkl_netdev_linux_fdnet entry for virtio-net + */ +struct lkl_netdev_linux_fdnet *lkl_register_netdev_linux_fdnet(int fd); + + +/** + * lkl_unregister_netdev_linux_fdnet - unregister a file descriptor-based + * network device as a NIC + * + * @nd - a struct lkl_netdev_linux_fdnet entry to be unregistered + */ +void lkl_unregister_netdev_linux_fdnet(struct lkl_netdev_linux_fdnet *nd); + +#endif /* _VIRTIO_NET_LINUX_FDNET_H*/ diff --git a/tools/lkl/lib/virtio_net_raw.c b/tools/lkl/lib/virtio_net_raw.c new file mode 100644 index 00000000000000..ac6edd42e71526 --- /dev/null +++ b/tools/lkl/lib/virtio_net_raw.c @@ -0,0 +1,69 @@ +/* + * raw socket based virtual network interface feature for LKL + * Copyright (c) 2015,2016 Ryo Nakamura, Hajime Tazaki + * + * Author: Ryo Nakamura + * Hajime Tazaki + * + * Current implementation is linux-specific. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virtio.h" +#include "virtio_net_linux_fdnet.h" + +/* since Linux 3.14 (man 7 packet) */ +#ifndef PACKET_QDISC_BYPASS +#define PACKET_QDISC_BYPASS 20 +#endif + +struct lkl_netdev *lkl_netdev_raw_create(const char *ifname) +{ + struct lkl_netdev_linux_fdnet *nd; + int ret; + struct sockaddr_ll ll; + int fd, fd_flags, val; + + fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (fd < 0) { + perror("socket"); + return NULL; + } + + memset(&ll, 0, sizeof(ll)); + ll.sll_family = PF_PACKET; + ll.sll_ifindex = if_nametoindex(ifname); + ll.sll_protocol = htons(ETH_P_ALL); + ret = bind(fd, (struct sockaddr *)&ll, sizeof(ll)); + if (ret) { + perror("bind"); + close(fd); + return NULL; + } + + val = 1; + ret = setsockopt(fd, SOL_PACKET, PACKET_QDISC_BYPASS, &val, + sizeof(val)); + if (ret) + perror("PACKET_QDISC_BYPASS, ignoring"); + + fd_flags = fcntl(fd, F_GETFD, NULL); + fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK); + + nd = lkl_register_netdev_linux_fdnet(fd); + if (!nd) { + perror("failed to register to."); + return NULL; + } + + return (struct lkl_netdev *)nd; +} diff --git a/tools/lkl/lib/virtio_net_tap.c b/tools/lkl/lib/virtio_net_tap.c index 72dd40e06cf33b..2013b33b936102 100644 --- a/tools/lkl/lib/virtio_net_tap.c +++ b/tools/lkl/lib/virtio_net_tap.c @@ -13,209 +13,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include - -#include #include "virtio.h" -#include "virtio_net_tap.h" - -struct lkl_netdev_tap { - struct lkl_netdev dev; - /* TAP device */ - int fd; - /* Needed to initiate shutdown */ - int eventfd; - /* epoll fds for rx and tx */ - int epoll_rx_fd; - int epoll_tx_fd; -}; - -struct lkl_netdev_tap_ops lkl_netdev_tap_ops = { - /* /dev/net/tun is Linux specific so we know our host is some - * flavor of Linux, but this allows graceful support if we're - * on a kernel that's < 2.6.22. */ - #ifdef __NR_eventfd - /* This sigature was recently (9/2014) changed in glibc. */ - .eventfd = (int (*)(unsigned int, int))eventfd, - #endif /* __NR_eventfd */ -}; - -static int net_tx(struct lkl_netdev *nd, void *data, int len) -{ - int ret; - struct lkl_netdev_tap *nd_tap = (struct lkl_netdev_tap *) nd; - - do { - ret = write(nd_tap->fd, data, len); - } while (ret == -1 && errno == EINVAL); - if (ret > 0) return 0; - if (ret < 0 && errno != EAGAIN) { - perror("write to tap fails"); - } - return -1; -} - -static int net_rx(struct lkl_netdev *nd, void *data, int *len) -{ - int ret; - struct lkl_netdev_tap *nd_tap = (struct lkl_netdev_tap *) nd; - - do { - ret = read(nd_tap->fd, data, *len); - } while (ret == -1 && errno == EINVAL); - if (ret > 0) { - *len = ret; - return 0; - } - if (ret < 0 && errno != EAGAIN) { - perror("read from tap fails"); - } - return -1; -} - -static int net_poll(struct lkl_netdev *nd, int events) -{ - struct lkl_netdev_tap *nd_tap = container_of(nd, struct lkl_netdev_tap, dev); - int epoll_fd = -1; - struct epoll_event ev[2]; - int ret; - const int is_rx = events & LKL_DEV_NET_POLL_RX; - const int is_tx = events & LKL_DEV_NET_POLL_TX; - int i; - int ret_ev = 0; - unsigned int event; - - if (is_rx && is_tx) { - fprintf(stderr, "both LKL_DEV_NET_POLL_RX and LKL_DEV_NET_POLL_TX" - "are set\n"); - lkl_host_ops.panic(); - return -1; - } - if (!is_rx && !is_tx) { - fprintf(stderr, "Neither LKL_DEV_NET_POLL_RX nor" - "LKL_DEV_NET_POLL_TX are set.\n"); - lkl_host_ops.panic(); - return -1; - } - - if (is_rx) - epoll_fd = nd_tap->epoll_rx_fd; - else if (is_tx) - epoll_fd = nd_tap->epoll_tx_fd; - - do { - ret = epoll_wait(epoll_fd, ev, 2, -1); - } while (ret == -1 && errno == EINTR); - if (ret < 0) { - perror("epoll_wait"); - return -1; - } - - for (i = 0; i < ret; ++i) { - if (ev[i].data.fd == nd_tap->eventfd) { - return -1; - } - if (ev[i].data.fd == nd_tap->fd) { - event = ev[i].events; - if(event & (EPOLLIN | EPOLLPRI)) - ret_ev = LKL_DEV_NET_POLL_RX; - else if (event & EPOLLOUT) - ret_ev = LKL_DEV_NET_POLL_TX; - else - return -1; - } - } - return ret_ev; -} - -static int net_close(struct lkl_netdev *nd) -{ - long buf = 1; - struct lkl_netdev_tap *nd_tap = container_of(nd, struct lkl_netdev_tap, dev); - - if (nd_tap->eventfd == -1) { - /* No eventfd support. */ - return 0; - } - - if (write(nd_tap->eventfd, &buf, sizeof(buf)) < 0) { - perror("tap: failed to close tap"); - /* This should never happen. */ - return -1; - } - - /* The order that we join in doesn't matter. */ - if (lkl_host_ops.thread_join(nd->rx_tid) || - lkl_host_ops.thread_join(nd->tx_tid)) - return -1; - - /* nor does the order that we close */ - if (close(nd_tap->fd) || close(nd_tap->eventfd) || - close(nd_tap->epoll_rx_fd) || close(nd_tap->epoll_tx_fd)) { - perror("tap net_close TAP fd"); - return -1; - } - - return 0; -} - -struct lkl_dev_net_ops tap_net_ops = { - .tx = net_tx, - .rx = net_rx, - .poll = net_poll, - .close = net_close, -}; - -static int add_to_epoll(int epoll_fd, int fd, unsigned int events) -{ - struct epoll_event ev; - memset(&ev, 0, sizeof(ev)); - ev.events = events; - ev.data.fd = fd; - int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); - if (ret) { - perror("EPOLL_CTL_ADD fails"); - return -1; - } - return 0; -} - -static int create_epoll_fd(int fd, unsigned int events) { - int ret = epoll_create1(0); - if (ret < 0) { - perror("epoll_create1"); - return -1; - } - if (add_to_epoll(ret, fd, events)) { - close(ret); - return -1; - } - return ret; -} +#include "virtio_net_linux_fdnet.h" struct lkl_netdev *lkl_netdev_tap_create(const char *ifname) { - struct lkl_netdev_tap *nd; - int ret; - - nd = (struct lkl_netdev_tap *) malloc(sizeof(struct lkl_netdev_tap)); - if (!nd) { - fprintf(stderr, "tap: failed to allocate memory\n"); - /* TODO: propagate the error state, maybe use errno for that? */ - return NULL; - } + struct lkl_netdev_linux_fdnet *nd; + int fd, ret; struct ifreq ifr = { .ifr_flags = IFF_TAP | IFF_NO_PI, @@ -223,58 +32,25 @@ struct lkl_netdev *lkl_netdev_tap_create(const char *ifname) strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - nd->fd = open("/dev/net/tun", O_RDWR|O_NONBLOCK); - if (nd->fd < 0) { + fd = open("/dev/net/tun", O_RDWR|O_NONBLOCK); + if (fd < 0) { perror("tap: failed to open tap"); - free(nd); return NULL; } - ret = ioctl(nd->fd, TUNSETIFF, &ifr); + ret = ioctl(fd, TUNSETIFF, &ifr); if (ret < 0) { fprintf(stderr, "tap: failed to attach to %s: %s\n", ifr.ifr_name, strerror(errno)); - close(nd->fd); - free(nd); + close(fd); return NULL; } - /* Making them edge-triggered to save CPU. */ - nd->epoll_rx_fd = create_epoll_fd(nd->fd, EPOLLIN | EPOLLPRI | EPOLLET); - nd->epoll_tx_fd = create_epoll_fd(nd->fd, EPOLLOUT | EPOLLET); - if (nd->epoll_rx_fd < 0 || nd->epoll_tx_fd < 0) { - if (nd->epoll_rx_fd >= 0) close(nd->epoll_rx_fd); - if (nd->epoll_tx_fd >= 0) close(nd->epoll_tx_fd); - close(nd->fd); - free(nd); + + nd = lkl_register_netdev_linux_fdnet(fd); + if (!nd) { + perror("failed to register to."); return NULL; } - nd->dev.ops = &tap_net_ops; - if (lkl_netdev_tap_ops.eventfd) { - /* eventfd is supported by the host, all is well */ - nd->eventfd = lkl_netdev_tap_ops.eventfd( - 0, EFD_NONBLOCK | EFD_SEMAPHORE); - - if (nd->eventfd < 0) { - perror("lkl_netdev_tap_create eventfd"); - goto fail; - } - if (add_to_epoll(nd->epoll_rx_fd, nd->eventfd, EPOLLIN) || - add_to_epoll(nd->epoll_tx_fd, nd->eventfd, EPOLLIN)) { - close(nd->eventfd); - goto fail; - } - } else { - /* no host eventfd support */ - nd->eventfd = -1; - } return (struct lkl_netdev *)nd; -fail: - close(nd->epoll_rx_fd); - close(nd->epoll_tx_fd); - close(nd->fd); - free(nd); - return NULL; - - } diff --git a/tools/lkl/lib/virtio_net_tap.h b/tools/lkl/lib/virtio_net_tap.h deleted file mode 100644 index 4069c7c4fd0ccd..00000000000000 --- a/tools/lkl/lib/virtio_net_tap.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _VIRTIO_NET_TAP_H -#define _VIRTIO_NET_TAP_H - -extern struct lkl_netdev_tap_ops { - /* We need this so that we can "unhijack" this function in - * case we decided to hijack it. */ - int (*eventfd)(unsigned int initval, int flags); -} lkl_netdev_tap_ops; - -#endif /* _VIRTIO_NET_TAP_H*/ diff --git a/tools/lkl/tests/net-test.c b/tools/lkl/tests/net-test.c index c86e6428d54e29..90225e6ff21b59 100644 --- a/tools/lkl/tests/net-test.c +++ b/tools/lkl/tests/net-test.c @@ -89,7 +89,7 @@ static int test_icmp(char *str, int len) return TEST_FAILURE; } - ret = lkl_sys_recv(sock, buf, sizeof(buf), 0); + ret = lkl_sys_recv(sock, buf, sizeof(buf), MSG_DONTWAIT); if (ret < 0) { snprintf(str, len, "recv error (%s)", strerror(errno)); return TEST_FAILURE; @@ -116,7 +116,7 @@ static int test_net_init(int argc, char **argv) struct lkl_netdev *nd = NULL; if (argc < 6) { - printf("usage %s [gateway]\n", argv[0]); + printf("usage %s [gateway]\n", argv[0]); exit(0); } @@ -127,7 +127,7 @@ static int test_net_init(int argc, char **argv) dst = argv[5]; if (argc == 7) - gateway = argv[5]; + gateway = argv[6]; if (iftype && ifname && (strncmp(iftype, "tap", 3) == 0)) nd = lkl_netdev_tap_create(ifname); @@ -135,6 +135,8 @@ static int test_net_init(int argc, char **argv) else if (iftype && ifname && (strncmp(iftype, "dpdk", 4) == 0)) nd = lkl_netdev_dpdk_create(ifname); #endif /* CONFIG_AUTO_LKL_VIRTIO_NET_DPDK */ + else if (iftype && ifname && (strncmp(iftype, "raw", 3) == 0)) + nd = lkl_netdev_raw_create(ifname); if (!nd) { fprintf(stderr, "init netdev failed\n"); diff --git a/tools/lkl/tests/net.sh b/tools/lkl/tests/net.sh index 3ff3f787e65bf1..0fe9ee021d8303 100755 --- a/tools/lkl/tests/net.sh +++ b/tools/lkl/tests/net.sh @@ -1,5 +1,10 @@ #!/bin/bash -e +IFNAME=`ip route |grep default | awk '{print $5}'` +GW=`ip route |grep default | awk '{print $3}'` +IPADDR=`echo $GW | sed -r "s/([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/\1\`expr \2 + 10\`/"` +PLEN=`ip rou |grep ${IFNAME} | grep "scope link" | awk '{print $1}' | sed "s/.*\/\(.*\)/\1/"` + echo "== TAP (LKL net) tests ==" if [ -c /dev/net/tun ]; then sudo ip link set dev lkl_ptt1 down || true @@ -14,6 +19,15 @@ if [ -c /dev/net/tun ]; then sudo ip tuntap del dev lkl_ptt1 mode tap fi +echo "== RAW socket (LKL net) tests ==" +# currently not supported mingw +if [ -n "`printenv CONFIG_AUTO_LKL_POSIX_HOST`" ] ; then + sudo ip link set dev ${IFNAME} promisc on + # this won't work if IFNAME is wifi since it rewrites the src macaddr + sudo ./net-test raw ${IFNAME} ${IPADDR} ${PLEN} 8.8.8.8 ${GW} + sudo ip link set dev ${IFNAME} promisc off +fi + # we disabled this DPDK test because it's unlikely possible to describe # a generic set of commands for all environments to test with DPDK. users # may customize those test commands for your host.