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

(RFC) Improve network bandwidth by using shared memory between tender and bindings for hvt #290

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ endif
COMMON_LDFLAGS=-nostdlib -z max-page-size=0x1000
LDFLAGS=$(COMMON_LDFLAGS) -static $(HOST_LDFLAGS)
# CFLAGS used for building bindings/ and in-tree tests.
INCDIR=-isystem $(TOP)/include/crt -I$(TOP)/include/solo5
INCDIR=-isystem $(TOP)/include/crt -I$(TOP)/include/solo5 -I$(TOP)/bindings/muen
CFLAGS=$(MD_CFLAGS) -std=gnu99 -Wall -Wextra -Werror -O2 -g $(INCDIR)

# Genode linking is a special case
Expand Down
11 changes: 8 additions & 3 deletions bindings/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

include $(TOP)/Makefile.common

SHM_COBJS=\
muen/channel.o \
muen/reader.o \
muen/shm_net.o \
muen/writer.o

COMMON_COBJS=\
abort.o \
cpu_${TARGET_ARCH}.o \
Expand All @@ -38,6 +44,7 @@ hvt/time.o

HVT_COBJS=\
$(COMMON_HVT_COBJS) \
$(SHM_COBJS) \
hvt/platform_lifecycle.o \
hvt/yield.o \
hvt/tscclock.o \
Expand All @@ -64,9 +71,7 @@ $(COMMON_COBJS)

MUEN_COBJS=\
$(COMMON_HVT_COBJS) \
muen/channel.o \
muen/reader.o \
muen/writer.o \
$(SHM_COBJS) \
muen/muen-block.o \
muen/muen-clock.o \
muen/muen-console.o \
Expand Down
2 changes: 2 additions & 0 deletions bindings/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ typedef enum {
INFO,
DEBUG,
} log_level_t;
#ifdef __SOLO5_BINDINGS__
int log(log_level_t level, const char *fmt, ...);
#endif
void log_set_level(log_level_t level);

/* compiler-only memory "barrier" */
Expand Down
82 changes: 69 additions & 13 deletions bindings/hvt/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,73 @@
*/

#include "bindings.h"
#include "shm_net.h"
#include "sinfo.h"
#include "reader.h"
#include "writer.h"

struct muchannel *tx_channel;
struct muchannel *rx_channel;
struct muchannel_reader net_rdr;
bool shm_enabled = false;

solo5_result_t solo5_net_queue(const uint8_t *buf, size_t size)
{
int ret;

assert(shm_enabled);
ret = shm_net_write(tx_channel, buf, size);
return shm_to_solo5_result(ret);
}

void solo5_net_flush()
{
assert(shm_enabled);
hvt_do_hypercall(HVT_HYPERCALL_NET_NOTIFY, NULL);
}

solo5_result_t solo5_net_write(const uint8_t *buf, size_t size)
{
volatile struct hvt_netwrite wr;
int ret = 0;
if (shm_enabled) {
ret = solo5_net_queue(buf, size);
solo5_net_flush();
return ret;
} else {
volatile struct hvt_netwrite wr;

wr.data = buf;
wr.len = size;
wr.ret = 0;
wr.data = buf;
wr.len = size;
wr.ret = 0;

hvt_do_hypercall(HVT_HYPERCALL_NETWRITE, &wr);
hvt_do_hypercall(HVT_HYPERCALL_NETWRITE, &wr);

return (wr.ret == 0 && wr.len == size) ? SOLO5_R_OK : SOLO5_R_EUNSPEC;
return (wr.ret == 0 && wr.len == size) ? SOLO5_R_OK : SOLO5_R_EUNSPEC;
}
}

solo5_result_t solo5_net_read(uint8_t *buf, size_t size, size_t *read_size)
{
volatile struct hvt_netread rd;
int ret = 0;
if (shm_enabled) {
ret = shm_net_read(rx_channel, &net_rdr,
buf, size, read_size);

rd.data = buf;
rd.len = size;
rd.ret = 0;
if (ret == SHM_NET_XON) {
hvt_do_hypercall(HVT_HYPERCALL_NET_XON, NULL);
}
return shm_to_solo5_result(ret);
} else {
volatile struct hvt_netread rd;

hvt_do_hypercall(HVT_HYPERCALL_NETREAD, &rd);
rd.data = buf;
rd.len = size;
rd.ret = 0;

*read_size = rd.len;
return (rd.ret == 0) ? SOLO5_R_OK : SOLO5_R_AGAIN;
hvt_do_hypercall(HVT_HYPERCALL_NETREAD, &rd);
*read_size = rd.len;
return (rd.ret == 0) ? SOLO5_R_OK : SOLO5_R_AGAIN;
}
}

void solo5_net_info(struct solo5_net_info *info)
Expand All @@ -61,4 +102,19 @@ void solo5_net_info(struct solo5_net_info *info)

void net_init(void)
{
struct hvt_shm_info ni;

memset(&ni, 0, sizeof(ni));
hvt_do_hypercall(HVT_HYPERCALL_SHMINFO, &ni);

shm_enabled = ni.shm_enabled;

if (shm_enabled) {
tx_channel = (struct muchannel *)ni.tx_channel_addr;
rx_channel = (struct muchannel *)ni.rx_channel_addr;

muen_channel_init_writer(tx_channel, MUENNET_PROTO, sizeof(struct net_msg),
ni.tx_channel_addr_size, 10, 1);
muen_channel_init_reader(&net_rdr, MUENNET_PROTO);
}
}
9 changes: 8 additions & 1 deletion bindings/muen/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@ struct muchannel_header {
uint64_t protocol;
uint64_t size;
uint64_t elements;
uint64_t __reserved;
uint64_t rc;
uint64_t wsc;
uint64_t wc;
} __attribute__((packed, aligned(8)));

struct muchannel_misc {
uint8_t xon_enabled;
uint8_t xon;
uint8_t reserved[6];
};

struct muchannel {
struct muchannel_header hdr;
struct muchannel_misc misc;
char data[];
};

Expand Down
2 changes: 1 addition & 1 deletion bindings/muen/muen-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void console_init(void)
epoch = muen_get_sched_start();
channel_out = (struct muchannel *)(channel->data.mem.address);
muen_channel_init_writer(channel_out, DEBUGLOG_PROTO, sizeof(struct log_msg),
channel->data.mem.size, epoch);
channel->data.mem.size, epoch, 0);
log(INFO, "Solo5: Console: Muen Channel @ 0x%lx, size 0x%lx, epoch 0x%lx\n",
channel->data.mem.address, channel->data.mem.size, epoch);
}
47 changes: 8 additions & 39 deletions bindings/muen/muen-net.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,56 +19,25 @@
*/

#include "../hvt/bindings.h"
#include "shm_net.h"
#include "sinfo.h"
#include "reader.h"
#include "writer.h"

#define PACKET_SIZE 1514
#define MUENNET_PROTO 0x7ade5c549b08e814ULL

struct net_msg {
uint8_t data[PACKET_SIZE];
uint16_t length;
} __attribute__((packed));

static struct muchannel *net_in;
static struct muchannel *net_out;
static struct muchannel_reader net_rdr;

struct muchannel *net_in;
struct muchannel *net_out;
struct muchannel_reader net_rdr;
static uint8_t mac_addr[6];

solo5_result_t solo5_net_write(const uint8_t *buf, size_t size)
{
struct net_msg pkt;

if (size > PACKET_SIZE)
return SOLO5_R_EINVAL;

memset(&pkt, 0, sizeof(struct net_msg));
cc_barrier();
pkt.length = size;
memcpy(&pkt.data, buf, size);
muen_channel_write(net_out, &pkt);

return SOLO5_R_OK;
return shm_to_solo5_result(shm_net_write(net_out, buf, size));
}

solo5_result_t solo5_net_read(uint8_t *buf, size_t size, size_t *read_size)
{
enum muchannel_reader_result result;
struct net_msg pkt;

if (size < PACKET_SIZE)
return SOLO5_R_EINVAL;

result = muen_channel_read(net_in, &net_rdr, &pkt);
if (result == MUCHANNEL_SUCCESS) {
memcpy(buf, &pkt.data, pkt.length);
*read_size = pkt.length;
return SOLO5_R_OK;
} else {
return SOLO5_R_AGAIN;
}
return shm_to_solo5_result(shm_net_read(net_in, &net_rdr, buf,
size, read_size));
}

bool muen_net_pending_data()
Expand Down Expand Up @@ -129,7 +98,7 @@ void net_init(void)

net_out = (struct muchannel *)(chan_out->data.mem.address);
muen_channel_init_writer(net_out, MUENNET_PROTO, sizeof(struct net_msg),
chan_out->data.mem.size, epoch);
chan_out->data.mem.size, epoch, 0);
log(INFO, "Solo5: Net: Muen shared memory stream, protocol 0x%lx\n",
MUENNET_PROTO);
log(INFO, "Solo5: Net: Output channel @ 0x%lx, size 0x%lx, epoch 0x%lx\n",
Expand Down
2 changes: 1 addition & 1 deletion bindings/muen/muen-yield.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "../bindings.h"
#include "muen-net.h"

bool solo5_yield(uint64_t deadline)
bool solo5_yield(solo5_time_t deadline)
{
bool rc = false;
do {
Expand Down
12 changes: 10 additions & 2 deletions bindings/muen/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ void muen_channel_init_reader(struct muchannel_reader *reader, uint64_t protocol
}

enum muchannel_reader_result muen_channel_read(
const struct muchannel * const channel,
struct muchannel *channel,
struct muchannel_reader *reader,
void *element)
{
uint64_t epoch, pos, wc, wsc;
uint64_t epoch, pos, wc, wsc, xon;
enum muchannel_reader_result result;

if (muen_channel_is_active(channel)) {
Expand All @@ -90,11 +90,19 @@ enum muchannel_reader_result muen_channel_read(
cc_barrier();

serialized_copy(&channel->hdr.wsc, &wsc);
serialized_copy((uint64_t *)&channel->misc.xon, &xon);
if (wsc - reader->rc > reader->elements) {
result = MUCHANNEL_OVERRUN_DETECTED;
} else {
result = MUCHANNEL_SUCCESS;
reader->rc++;
if (channel->misc.xon_enabled && !xon &&
(wsc - reader->rc < ((20 * reader->elements) / 100))) {
xon = 1;
serialized_copy(&xon, (uint64_t *)&channel->misc.xon);
result = MUCHANNEL_XON;
}
serialized_copy(&reader->rc, &channel->hdr.rc);
}
if (has_epoch_changed(channel, reader)) {
result = MUCHANNEL_EPOCH_CHANGED;
Expand Down
3 changes: 2 additions & 1 deletion bindings/muen/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum muchannel_reader_result {
MUCHANNEL_EPOCH_CHANGED,
MUCHANNEL_NO_DATA,
MUCHANNEL_OVERRUN_DETECTED,
MUCHANNEL_XON,
MUCHANNEL_SUCCESS
};

Expand All @@ -49,7 +50,7 @@ void muen_channel_init_reader(struct muchannel_reader *reader, uint64_t protocol
* Read next element from given channel.
*/
enum muchannel_reader_result muen_channel_read(
const struct muchannel * const channel,
struct muchannel *channel,
struct muchannel_reader *reader,
void *element);

Expand Down
73 changes: 73 additions & 0 deletions bindings/muen/shm_net.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017 Contributors as noted in the AUTHORS file
*
* This file is part of Solo5, a unikernel base layer.
*
* Permission to use, copy, modify, and/or distribute this software
* for any purpose with or without fee is hereby granted, provided
* that the above copyright notice and this permission notice appear
* in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../hvt/bindings.h"
#include "sinfo.h"
#include "reader.h"
#include "writer.h"
#include "shm_net.h"
#ifndef __SOLO5_BINDINGS__
#include "assert.h"
#endif

shm_net_result_t shm_net_write(struct muchannel *channel,
const uint8_t *buf, size_t size)
{
struct net_msg pkt;

if (size > PACKET_SIZE) {
return SHM_NET_EINVAL;
}

memset(&pkt, 0, sizeof(struct net_msg));
cc_barrier();
pkt.length = size;
memcpy(&pkt.data, buf, size);
if (muen_channel_write(channel, &pkt) != 0) {
return SHM_NET_AGAIN;
}

return SHM_NET_OK;
}

shm_net_result_t shm_net_read(struct muchannel *channel,
struct muchannel_reader *reader,
uint8_t *buf, size_t size, size_t *read_size)
{
enum muchannel_reader_result result;
struct net_msg pkt;

if (size < PACKET_SIZE)
return SHM_NET_EINVAL;

result = muen_channel_read(channel, reader, &pkt);
if (result == MUCHANNEL_SUCCESS || result == MUCHANNEL_XON) {
memcpy(buf, &pkt.data, pkt.length);
*read_size = pkt.length;
if (result == MUCHANNEL_XON) {
return SHM_NET_XON;
}
return SHM_NET_OK;
} else if (result == MUCHANNEL_NO_DATA || result == MUCHANNEL_INACTIVE) {
return SHM_NET_AGAIN;
} else if (result == MUCHANNEL_EPOCH_CHANGED) {
return SHM_NET_EPOCH_CHANGED;
}
return SHM_NET_EINVAL;
}
Loading