Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add networking support for raspi #10

Open
wants to merge 4 commits into
base: rump-hypcall-next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions tools/lkl/Makefile.autoconf
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ define virtio_net_dpdk
LDFLAGS +=-Wl,--whole-archive $$(DPDK_LIBS) -Wl,--no-whole-archive -lm -ldl
endef

define virtio_net_raspi
$(call set_autoconf_var,VIRTIO_NET_RASPI,y)
endef

define virtio_net_vde
$(call set_autoconf_var,VIRTIO_NET_VDE,y)
LDLIBS += $(shell pkg-config --libs vdeplug)
Expand Down Expand Up @@ -104,6 +108,7 @@ define rump_host

# if on arm-none-eabi baremetal, skip virio-host build
$(if $(filter $(CROSS_COMPILE),arm-none-eabi-),\
$(call virtio_net_raspi)
CFLAGS += -Iinclude/arm-none-eabi,\
CFLAGS += -pthread)

Expand Down
13 changes: 13 additions & 0 deletions tools/lkl/include/lkl.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,19 @@ lkl_netdev_tap_create(const char *ifname, int offload)
}
#endif

/**
* lkl_netdev_raspi_create - create raspi net_device for the virtio net backend
*/
#ifdef LKL_HOST_CONFIG_VIRTIO_NET_RASPI
struct lkl_netdev *lkl_netdev_raspi_create(void);
#else
static inline struct lkl_netdev *
lkl_netdev_raspi_create(void)
{
return NULL;
}
#endif

/**
* lkl_netdev_dpdk_create - create DPDK net_device for the virtio net backend
*
Expand Down
2 changes: 2 additions & 0 deletions tools/lkl/lib/Build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ liblkl-$(LKL_HOST_CONFIG_POSIX) += virtio_net_raw.o
liblkl-$(LKL_HOST_CONFIG_VIRTIO_NET_MACVTAP) += virtio_net_macvtap.o
liblkl-$(LKL_HOST_CONFIG_VIRTIO_NET_DPDK) += virtio_net_dpdk.o
liblkl-$(LKL_HOST_CONFIG_VIRTIO_NET_VDE) += virtio_net_vde.o
liblkl-$(LKL_HOST_CONFIG_VIRTIO_NET_RASPI) += virtio_net_raspi.o
liblkl-$(LKL_HOST_CONFIG_POSIX) += virtio_net_pipe.o
liblkl-$(LKL_HOST_CONFIG_RUMP) += rump.o
liblkl-$(LKL_HOST_CONFIG_RUMP) += rump-host.o
Expand All @@ -35,3 +36,4 @@ CFLAGS_rump-host.o = -I$(RUMP_PREFIX)/../platform/include \
-I../../ \
-DCONFIG_AUTO_LKL_POSIX_HOST -DCONFIG_LKL
CFLAGS_rump-sysproxy.o += -I$(OUTPUT)/../../include
CFLAGS_virtio_net_raspi.o += -I$(RUMP_PREFIX)/../platform/qemu-arm/include
63 changes: 37 additions & 26 deletions tools/lkl/lib/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,43 @@ int lkl_load_config_env(struct lkl_config *cfg)

if (!cfg)
return -1;
if (envtap || enviftype)
cfg->ifnum = 1;

/* general config */
ret = cfgcpy(&cfg->gateway, envgateway);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->gateway6, envgateway6);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->debug, envdebug);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->mount, envmount);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->single_cpu, envsingle_cpu);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->sysctls, envsysctls);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->boot_cmdline, envboot_cmdline);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->dump, envdump);
if (ret < 0)
return ret;

/* network config */
if (!(envtap || enviftype))
return 0;

iface = malloc(sizeof(struct lkl_config_iface));
if (!iface)
return -1;
memset(iface, 0, sizeof(struct lkl_config_iface));
cfg->ifnum = 1;
cfg->ifaces = iface;

ret = cfgcpy(&iface->iftap, envtap);
if (ret < 0)
Expand Down Expand Up @@ -315,30 +347,7 @@ int lkl_load_config_env(struct lkl_config *cfg)
ret = cfgcpy(&iface->ifqdisc_entries, envqdisc_entries);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->gateway, envgateway);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->gateway6, envgateway6);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->debug, envdebug);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->mount, envmount);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->single_cpu, envsingle_cpu);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->sysctls, envsysctls);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->boot_cmdline, envboot_cmdline);
if (ret < 0)
return ret;
ret = cfgcpy(&cfg->dump, envdump);
if (ret < 0)
return ret;

return 0;
}

Expand Down Expand Up @@ -492,6 +501,8 @@ static int lkl_config_netdev_create(struct lkl_config *cfg,
mac);
} else if ((strcmp(iface->iftype, "pipe") == 0)) {
nd = lkl_netdev_pipe_create(iface->ifparams, offload);
} else if ((strcmp(iface->iftype, "raspi") == 0)) {
nd = lkl_netdev_raspi_create();
} else {
if (offload) {
lkl_printf("WARN: %s isn't supported on %s\n",
Expand Down
4 changes: 2 additions & 2 deletions tools/lkl/lib/endian.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#define le16toh(x) (x)
#define le32toh(x) (x)
#define le64toh(x) (x)
#define htole16(x) htons(x)
#define htole32(x) htonl(x)
#define htole16(x) (x)
#define htole32(x) (x)
#define htobe16(x) htons(x)
#define htobe32(x) htonl(x)
#define be32toh(x) ntohl(x)
Expand Down
14 changes: 11 additions & 3 deletions tools/lkl/lib/iomem.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@
#define IOMEM_OFFSET_BITS 24
#define MAX_IOMEM_REGIONS 256

#ifdef LKL_HOST_CONFIG_VIRTIO_NET_RASPI
extern char __iomem_start;
static char *iomem_base = &__iomem_start;
#else
static char *const iomem_base; /* = 0 */
#endif

#define IOMEM_ADDR_TO_INDEX(addr) \
(((uintptr_t)addr) >> IOMEM_OFFSET_BITS)
(((uintptr_t)addr - (uintptr_t)iomem_base) >> IOMEM_OFFSET_BITS)
#define IOMEM_ADDR_TO_OFFSET(addr) \
(((uintptr_t)addr) & ((1 << IOMEM_OFFSET_BITS) - 1))
(((uintptr_t)addr - (uintptr_t)iomem_base) & \
((1 << IOMEM_OFFSET_BITS) - 1))
#define IOMEM_INDEX_TO_ADDR(i) \
(void *)(uintptr_t)(i << IOMEM_OFFSET_BITS)
(void *)((uintptr_t)iomem_base + (uintptr_t)(i << IOMEM_OFFSET_BITS))

static struct iomem_region {
void *data;
Expand Down
6 changes: 6 additions & 0 deletions tools/lkl/lib/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ int lkl_if_up(int ifindex)
err = lkl_sys_ioctl(sock, LKL_SIOCSIFFLAGS, (long)&ifr);
}

// XXX: Workaround to avoid crashes in raspi
#ifndef LKL_HOST_CONFIG_VIRTIO_NET_RASPI
lkl_sys_close(sock);
#endif

return err;
}
Expand Down Expand Up @@ -596,7 +599,10 @@ static int ipaddr_modify(int cmd, int flags, int ifindex, int af, void *addr,

err = rtnl_talk(fd, &req.n);

// XXX: Workaround to avoid crashes in raspi
#ifndef LKL_HOST_CONFIG_VIRTIO_NET_RASPI
lkl_sys_close(fd);
#endif
return err;
}

Expand Down
141 changes: 141 additions & 0 deletions tools/lkl/lib/virtio_net_raspi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include "virtio.h"

typedef uint8_t u8;
#include <raspi.h>


struct lkl_netdev_raspi {
struct lkl_netdev dev;
int is_closed;
uint8_t buffer[FRAME_BUFFER_SIZE];
};

static inline size_t min(size_t a, size_t b)
{
return (a > b) ? b : a;
}

static inline void platform_sleep(void)
{
typedef int64_t time_t;
struct __platform_timespec { time_t tv_sec; long tv_nsec; };
extern int __platform_clock_nanosleep(int clock_id, int flags,
const struct timespec *request,
struct timespec *remain);

struct __platform_timespec sl = {0, 0};

__platform_clock_nanosleep(3 /* == CLOCK_MONOTONIC */, 0, &sl, NULL);
}

static int net_tx(struct lkl_netdev *nd, struct iovec *iov, int cnt)
{
struct lkl_netdev_raspi *nd_raspi =
container_of(nd, struct lkl_netdev_raspi, dev);
void *buffer = nd_raspi->buffer;
int seg, sent = 0;

for (seg = 0; seg < cnt; seg++) {
void *data = iov[seg].iov_base;
size_t len = iov[seg].iov_len;
size_t remaining = FRAME_BUFFER_SIZE - sent;
size_t to_send = min(remaining, len);

if (remaining == 0)
break;
else if (len == 0)
continue;

memcpy(buffer + sent, iov[seg].iov_base, to_send);
sent += to_send;
}

if (sent > 0) {
int ok = cr_sendframe(buffer, sent);

if (!ok) {
sent = 0;
return -1;
}
}
return sent;
}

static int net_rx(struct lkl_netdev *nd, struct iovec *iov, int cnt)
{
struct lkl_netdev_raspi *nd_raspi =
container_of(nd, struct lkl_netdev_raspi, dev);
void *buffer = nd_raspi->buffer;
unsigned int size = 0;
size_t seg, copied = 0;
int ok;

ok = cr_recvframe(buffer, &size);
if (!ok)
return -1;

for (seg = 0; copied < size && seg < cnt; seg++) {
size_t to_copy = min(size - copied, iov[seg].iov_len);

memcpy(iov[seg].iov_base, buffer, to_copy);
copied += to_copy;
}

return copied;
}

static int net_poll(struct lkl_netdev *nd)
{
struct lkl_netdev_raspi *nd_raspi =
container_of(nd, struct lkl_netdev_raspi, dev);

if (nd_raspi->is_closed)
return LKL_DEV_NET_POLL_HUP;

// XXX: Necessary to avoid deadlocks
platform_sleep();

return LKL_DEV_NET_POLL_RX | LKL_DEV_NET_POLL_TX;
}

static void net_poll_hup(struct lkl_netdev *nd)
{
struct lkl_netdev_raspi *nd_raspi =
container_of(nd, struct lkl_netdev_raspi, dev);

nd_raspi->is_closed = 1;
}

static void net_free(struct lkl_netdev *nd)
{
struct lkl_netdev_raspi *nd_raspi =
container_of(nd, struct lkl_netdev_raspi, dev);

free(nd_raspi);
}

struct lkl_dev_net_ops raspi_net_ops = {
.tx = net_tx,
.rx = net_rx,
.poll = net_poll,
.poll_hup = net_poll_hup,
.free = net_free
};

struct lkl_netdev *lkl_netdev_raspi_create(void)
{
struct lkl_netdev_raspi *nd;

nd = malloc(sizeof(*nd));
if (!nd)
return NULL;

nd->is_closed = 0;
nd->dev.ops = &raspi_net_ops;
nd->dev.has_vnet_hdr = 0;
return nd;
}