aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/netfront.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-02-12 14:35:39 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-02-12 14:35:39 +0000
commit0243b256d6187ea610174531607366945e489605 (patch)
treefd2de9267b7493642626f8c84d7c81ebcd336bed /extras/mini-os/netfront.c
parent67bfbd67d1311a1a590b47e568a07622d4492873 (diff)
downloadxen-0243b256d6187ea610174531607366945e489605.tar.gz
xen-0243b256d6187ea610174531607366945e489605.tar.bz2
xen-0243b256d6187ea610174531607366945e489605.zip
Add stubdomain support. See stubdom/README for usage details.
- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in arch_limits.h so as to permit getting them from there without pulling all the internal Mini-OS defines. - Setup a xen-elf cross-compilation environment in stubdom/cross-root - Add a POSIX layer on top of Mini-OS by linking against the newlib C library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c - Cross-compile zlib and libpci too. - Add an xs.h-compatible layer on top of Mini-OS' xenbus. - Cross-compile libxc with an additional xc_minios.c and a few things disabled. - Cross-compile ioemu with an additional block-vbd, but without sound, tpm and other details. A few hacks are needed: - Align ide and scsi buffers at least on sector size to permit direct transmission to the block backend. While we are at it, just page-align it to possibly save a segment. Also, limit the scsi buffer size because of limitations of the block paravirtualization protocol. - Allocate big tables dynamically rather that letting them go to bss: when Mini-OS gets installed in memory, bss is not lazily allocated, and doing so during Mini-OS is unnecessarily trick while we can simply use malloc. - Had to change the Mini-OS compilation somehow, so as to export Mini-OS compilation flags to the Makefiles of libxc and ioemu. Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'extras/mini-os/netfront.c')
-rw-r--r--extras/mini-os/netfront.c98
1 files changed, 94 insertions, 4 deletions
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index e3c56c10c4..095f55ca15 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -19,7 +19,10 @@
DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
+#ifdef HAVE_LIBC
#define NETIF_SELECT_RX ((void*)-1)
+#endif
+
#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
@@ -50,6 +53,13 @@ struct netfront_dev {
char *nodename;
char *backend;
+#ifdef HAVE_LIBC
+ int fd;
+ unsigned char *data;
+ size_t len;
+ size_t rlen;
+#endif
+
void (*netif_rx)(unsigned char* data, int len);
};
@@ -92,7 +102,8 @@ moretodo:
cons = dev->rx.rsp_cons;
int nr_consumed=0;
- while ((cons != rp))
+ int some = 0;
+ while ((cons != rp) && !some)
{
struct net_buffer* buf;
unsigned char* page;
@@ -116,7 +127,18 @@ moretodo:
if(rx->status>0)
{
- dev->netif_rx(page+rx->offset,rx->status);
+#ifdef HAVE_LIBC
+ if (dev->netif_rx == NETIF_SELECT_RX) {
+ int len = rx->status;
+ ASSERT(current == main_thread);
+ if (len > dev->len)
+ len = dev->len;
+ memcpy(dev->data, page+rx->offset, len);
+ dev->rlen = len;
+ some = 1;
+ } else
+#endif
+ dev->netif_rx(page+rx->offset,rx->status);
}
nr_consumed++;
@@ -127,7 +149,7 @@ moretodo:
int more;
RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
- if(more) goto moretodo;
+ if(more && !some) goto moretodo;
RING_IDX req_prod = dev->rx.req_prod_pvt;
@@ -178,6 +200,9 @@ void network_tx_buf_gc(struct netfront_dev *dev)
if (txrsp->status == NETIF_RSP_NULL)
continue;
+ if (txrsp->status == NETIF_RSP_ERROR)
+ printk("packet error\n");
+
id = txrsp->id;
struct net_buffer* buf = &dev->tx_buffers[id];
gnttab_end_access(buf->gref);
@@ -218,6 +243,22 @@ void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
local_irq_restore(flags);
}
+#ifdef HAVE_LIBC
+void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int flags;
+ struct netfront_dev *dev = data;
+ int fd = dev->fd;
+
+ local_irq_save(flags);
+ network_tx_buf_gc(dev);
+ local_irq_restore(flags);
+
+ files[fd].read = 1;
+ wake_up(&netfront_queue);
+}
+#endif
+
struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6])
{
xenbus_transaction_t xbt;
@@ -266,7 +307,12 @@ struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned
dev->dom = op.remote_dom = xenbus_read_integer(path);
HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
clear_evtchn(op.port); /* Without, handler gets invoked now! */
- dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
+#ifdef HAVE_LIBC
+ if (thenetif_rx == NETIF_SELECT_RX)
+ dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev);
+ else
+#endif
+ dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
dev->evtchn=op.port;
txs = (struct netif_tx_sring*) alloc_page();
@@ -381,6 +427,23 @@ done:
return dev;
}
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename) {
+ struct netfront_dev *dev;
+
+ dev = init_netfront(nodename, NETIF_SELECT_RX, NULL);
+ if (!dev) {
+ printk("TAP open failed\n");
+ errno = EIO;
+ return -1;
+ }
+ dev->fd = alloc_fd(FTYPE_TAP);
+ printk("tap_open(%s) -> %d\n", nodename, dev->fd);
+ files[dev->fd].tap.dev = dev;
+ return dev->fd;
+}
+#endif
+
void shutdown_netfront(struct netfront_dev *dev)
{
char* err;
@@ -481,3 +544,30 @@ void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len)
network_tx_buf_gc(dev);
local_irq_restore(flags);
}
+
+#ifdef HAVE_LIBC
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len)
+{
+ unsigned long flags;
+ int fd = dev->fd;
+ ASSERT(current == main_thread);
+
+ dev->rlen = 0;
+ dev->data = data;
+ dev->len = len;
+
+ local_irq_save(flags);
+ network_rx(dev);
+ if (!dev->rlen)
+ /* No data for us, make select stop returning */
+ files[fd].read = 0;
+ /* Before re-enabling the interrupts, in case a packet just arrived in the
+ * meanwhile. */
+ local_irq_restore(flags);
+
+ dev->data = NULL;
+ dev->len = 0;
+
+ return dev->rlen;
+}
+#endif