Commit d3fa7ce7 authored by Brian Kocoloski's avatar Brian Kocoloski

update kitten xrbuf packet interface to perform xrbuf creation

rather than xrbuf attachment
parent 2364d746
......@@ -18,8 +18,8 @@
#include <lwk/types.h>
#include <lwk/kfs.h>
#include <lwk/workq.h>
#include <lwk/delay.h>
#include <lwk/poll.h>
#include <lwk/xpmem/xpmem.h>
#include <palacios/vmm_types.h>
......@@ -38,12 +38,6 @@
struct palacios_eth_device {
char dev_name[V3_NET_IF_NAMELEN];
struct kref refcount;
unsigned char xrbuf_attached;
/* information needed to generate ringbuffer */
unsigned int xrbuf_item_size;
unsigned int xrbuf_max_items;
xpmem_segid_t xrbuf_rx_segid;
/* ringbuffer for sending packets from the VM
* to the remote enclave
......@@ -59,7 +53,7 @@ struct palacios_eth_device {
struct file * anon_filp;
int connected;
struct work_struct work;
waitq_t intr_queue;
struct mutex mutex;
struct list_head node;
};
......@@ -118,46 +112,20 @@ __forget_eth(struct palacios_eth_device * eth)
list_del(&(eth->node));
}
void
eth_xrbuf_detach(struct work_struct * work)
{
struct palacios_eth_device * eth = container_of(work, struct palacios_eth_device, work);
int status;
status = xrbuf_detach(eth->xrbuf_rx);
if (status != 0)
ERROR("Failed to detach from xrbuf\n");
v3_lwk_printk("Eth dev %s torn down\n", eth->dev_name);
kmem_free(eth);
}
/* Final teardown on last kref_put */
static void
eth_last_put(struct kref * kref)
{
struct palacios_eth_device * eth = container_of(kref, struct palacios_eth_device, refcount);
int status;
/* This is pretty nasty ...
*
* When palacios tears down a VM, the teardown code, including for host-side
* interfaces such as this, is done by the user process, not the VM kernel
* thread.
*
* But we need to teardown xpmem state the was created by the kernel thread, so
* we can't do it directly ourselves
*
* In reality, the xpmem driver only cares about the aspace that is active, not
* necessarily the specific thread, so we can schedule delayed work to run via
* the kernel's work queue thread
*/
status = xrbuf_destroy(eth->xrbuf_rx);
if (status != 0)
ERROR("Failed to destroy xrbuf\n");
if (eth->xrbuf_attached) {
schedule_work(&(eth->work));
} else {
v3_lwk_printk("Eth dev %s torn down\n", eth->dev_name);
kmem_free(eth);
}
v3_lwk_printk("Eth dev %s torn down\n", eth->dev_name);
kmem_free(eth);
}
static ssize_t
......@@ -233,7 +201,25 @@ static unsigned int
packet_poll(struct file * filp,
struct poll_table_struct * poll_tb)
{
return 0;
struct palacios_eth_device * eth = (struct palacios_eth_device *)filp->private_data;
unsigned int mask = POLLOUT | POLLWRNORM;
mutex_lock(&(eth->mutex));
if (eth->connected == 0) {
mutex_unlock(&(eth->mutex));
return -ENODEV;
}
eth_get(eth);
mutex_unlock(&(eth->mutex));
poll_wait(filp, &(eth->intr_queue), poll_tb);
if (!xrbuf_is_empty(eth->xrbuf_rx))
mask |= (POLLIN | POLLRDNORM);
eth_put(eth);
return mask;
}
static int
......@@ -305,8 +291,8 @@ palacios_packet_open(char * host_if_name,
strncpy(eth->dev_name, host_if_name, V3_NET_IF_NAMELEN);
mutex_init(&(eth->mutex));
INIT_LIST_HEAD(&(eth->node));
INIT_WORK(&(eth->work), eth_xrbuf_detach);
kref_init(&(eth->refcount));
waitq_init(&(eth->intr_queue));
eth->v3_input_fn = input_fn;
eth->guest_priv_data = guest_priv_data;
......@@ -322,6 +308,15 @@ err_already:
return NULL;
}
#if 0
static int
kick(struct palacios_eth_device * eth)
{
waitq_wakeup(&(eth->intr_queue));
return 0;
}
#endif
static int
palacios_packet_send(void * priv_data,
unsigned char * pkt,
......@@ -331,38 +326,6 @@ palacios_packet_send(void * priv_data,
struct xrbuf_packet * xrbuf_pkt;
int status, sleep_time = 2000;
/*
* The packet interface is opened before userspace gives us the parameters
* of the ringbuffer, so we have to wait until now attach to the ringbuffer
*/
if (unlikely(eth->xrbuf_attached == 0) ) {
mutex_lock(&(eth->mutex));
if (eth->xrbuf_rx_segid == 0) {
ERROR("Cannot send data through packet iface: no segid passed from userspace\n");
mutex_unlock(&(eth->mutex));
return 0;
}
status = xrbuf_attach(
V3_XRBUF_XPMEM,
eth->xrbuf_item_size,
eth->xrbuf_max_items,
eth->xrbuf_rx_segid,
XRBUF_PRODUCER,
&(eth->xrbuf_rx)
);
if (status != 0) {
ERROR("Could not attach to xrbuf: cannot deliver packet\n");
return 0;
}
mutex_unlock(&(eth->mutex));
eth->xrbuf_attached = 1;
}
if (unlikely(len > ETHERNET_PACKET_LEN)) {
ERROR("Could not enqueue packet: size too large\n");
return 0;
......@@ -380,6 +343,11 @@ palacios_packet_send(void * priv_data,
if (sleep_time == 2000) {
WARNING("XRBUF_RX full ... sleeping for a bit but performance will suffer\n");
status = xrbuf_kick(eth->xrbuf_rx);
if (status != 0) {
ERROR("Could not kick xrbuf (error=%d)\n", status);
return 0;
}
}
mdelay(100);
......@@ -458,7 +426,7 @@ tap_connect(struct v3_guest * guest,
}
if (kcfg.xrbuf_item_size != sizeof(struct xrbuf_packet)) {
ERROR("Expecting item_size of %lu bytes -- user specified %lu bytes\n",
ERROR("Expecting item_size of %lu bytes -- user specified %u bytes\n",
sizeof(struct xrbuf_packet), kcfg.xrbuf_item_size);
return -EINVAL;
}
......@@ -470,7 +438,7 @@ tap_connect(struct v3_guest * guest,
if (eth == NULL) {
ERROR("Could not find eth interface for '%s'\n", kcfg.dev_name);
status = -ENODEV;
goto out_noput;
goto out_noeth;
}
mutex_lock(&(eth->mutex));
......@@ -478,7 +446,26 @@ tap_connect(struct v3_guest * guest,
if (eth->connected) {
ERROR("Eth interface '%s' already connected\n", eth->dev_name);
status = -EBUSY;
goto out_put;
goto out_already;
}
/* allocate RX xrbuf */
status = xrbuf_create(
V3_XRBUF_XPMEM,
kcfg.xrbuf_item_size,
kcfg.xrbuf_max_items,
XRBUF_PRODUCER,
&(eth->xrbuf_rx)
);
if (status != 0) {
ERROR("Could not create RX xrbuf\n");
goto out_xrbuf;
}
status = xrbuf_get_segid(eth->xrbuf_rx, &(kcfg.xrbuf_segid));
if (status != 0) {
ERROR("Could not get segid for RX xrbuf\n");
goto out_xrbuf_segid;
}
/* Allocate FD through which packets are transfered to/from userspace */
......@@ -486,7 +473,7 @@ tap_connect(struct v3_guest * guest,
if (fd < 0) {
ERROR("Could not create packet anon inode\n");
status = fd;
goto out_put;
goto out_kfs;
}
/* Write fd to userspace */
......@@ -495,19 +482,10 @@ tap_connect(struct v3_guest * guest,
if (copy_to_user((void __user *)arg, &kcfg, sizeof(struct v3_hobbes_tuntap_cfg))) {
ERROR("Could not copy to userspace\n");
kfs_close(eth->anon_filp);
fdTableInstallFd(current->fdTable, fd, 0);
status = -EFAULT;
goto out_put;
goto out_copy;
}
/* Save xrbuf params */
eth->xrbuf_item_size = kcfg.xrbuf_item_size;
eth->xrbuf_max_items = kcfg.xrbuf_max_items;
eth->xrbuf_rx_segid = kcfg.xrbuf_segid;
eth->connected = 1;
eth->guest = guest;
vm_get(eth->guest);
......@@ -516,11 +494,24 @@ tap_connect(struct v3_guest * guest,
v3_lwk_printk("TAP device '%s' connected\n", eth->dev_name);
status = 0;
out_put:
out_copy:
if (status != 0) {
kfs_close(eth->anon_filp);
fdTableInstallFd(current->fdTable, fd, 0);
}
out_kfs:
out_xrbuf_segid:
if (status != 0) {
(void)xrbuf_destroy(eth->xrbuf_rx);
}
out_xrbuf:
out_already:
mutex_unlock(&(eth->mutex));
eth_put(eth);
out_noput:
out_noeth:
mutex_unlock(&gbl_eth_mutex);
return status;
}
......
......@@ -163,14 +163,15 @@ struct v3_hobbes_stream_info {
struct v3_hobbes_tuntap_cfg {
/* input params */
char dev_name[V3_TUNTAP_IFNAME_LEN];
unsigned long xrbuf_item_size;
unsigned long xrbuf_max_items;
unsigned int xrbuf_item_size;
unsigned int xrbuf_max_items;
/* output params */
xpmem_segid_t xrbuf_segid;
int tap_fd;
} __attribute__((packed));
/**
* These are used by the kernel to forward events to Palacios.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment