# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1200585048 0
# Node ID 95558b4a6714c37ebd6db0fccc68f7f1197dd622
# Parent 6fdb108db46ca08700beb09a2189c6e6c124dc23
minios: support several netfronts
Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
extras/mini-os/include/netfront.h | 9 -
extras/mini-os/kernel.c | 2
extras/mini-os/netfront.c | 328 ++++++++++++++++++++------------------
3 files changed, 185 insertions(+), 154 deletions(-)
diff -r 6fdb108db46c -r 95558b4a6714 extras/mini-os/include/netfront.h
--- a/extras/mini-os/include/netfront.h Thu Jan 17 15:23:47 2008 +0000
+++ b/extras/mini-os/include/netfront.h Thu Jan 17 15:50:48 2008 +0000
@@ -1,2 +1,7 @@ void init_netfront(void*);
-void init_netfront(void*);
-void netfront_xmit(unsigned char* data,int len);
+#include <wait.h>
+struct netfront_dev;
+struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned
char *data, int len), unsigned char rawmac[6]);
+void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
+void shutdown_netfront(struct netfront_dev *dev);
+
+extern struct wait_queue_head netfront_queue;
diff -r 6fdb108db46c -r 95558b4a6714 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c Thu Jan 17 15:23:47 2008 +0000
+++ b/extras/mini-os/kernel.c Thu Jan 17 15:50:48 2008 +0000
@@ -82,7 +82,7 @@ static void periodic_thread(void *p)
static void netfront_thread(void *p)
{
- init_netfront(&start_info);
+ init_netfront(NULL, NULL, NULL);
}
/* This should be overridden by the application we are linked against. */
diff -r 6fdb108db46c -r 95558b4a6714 extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Thu Jan 17 15:23:47 2008 +0000
+++ b/extras/mini-os/netfront.c Thu Jan 17 15:50:48 2008 +0000
@@ -13,19 +13,13 @@
#include <gnttab.h>
#include <xmalloc.h>
#include <time.h>
+#include <netfront.h>
+#include <lib.h>
#include <semaphore.h>
-void init_rx_buffers(void);
-
-struct net_info {
- struct netif_tx_front_ring tx;
- struct netif_rx_front_ring rx;
- int tx_ring_ref;
- int rx_ring_ref;
- unsigned int evtchn, local_port;
-
-} net_info;
-
+DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
+
+#define NETIF_SELECT_RX ((void*)-1)
#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
@@ -33,16 +27,31 @@ struct net_info {
#define GRANT_INVALID_REF 0
-unsigned short rx_freelist[NET_RX_RING_SIZE];
-unsigned short tx_freelist[NET_TX_RING_SIZE];
-__DECLARE_SEMAPHORE_GENERIC(tx_sem, NET_TX_RING_SIZE);
-
struct net_buffer {
void* page;
- int gref;
+ grant_ref_t gref;
};
-struct net_buffer rx_buffers[NET_RX_RING_SIZE];
-struct net_buffer tx_buffers[NET_TX_RING_SIZE];
+
+struct netfront_dev {
+ unsigned short tx_freelist[NET_TX_RING_SIZE];
+ struct semaphore tx_sem;
+
+ struct net_buffer rx_buffers[NET_RX_RING_SIZE];
+ struct net_buffer tx_buffers[NET_TX_RING_SIZE];
+
+ struct netif_tx_front_ring tx;
+ struct netif_rx_front_ring rx;
+ grant_ref_t tx_ring_ref;
+ grant_ref_t rx_ring_ref;
+ evtchn_port_t evtchn, local_port;
+
+ char *nodename;
+ char *backend;
+
+ void (*netif_rx)(unsigned char* data, int len);
+};
+
+void init_rx_buffers(struct netfront_dev *dev);
static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
{
@@ -69,17 +78,16 @@ static inline int xennet_rxidx(RING_IDX
return idx & (NET_RX_RING_SIZE - 1);
}
-void network_rx(void)
-{
- struct net_info *np = &net_info;
+void network_rx(struct netfront_dev *dev)
+{
RING_IDX rp,cons;
struct netif_rx_response *rx;
moretodo:
- rp = np->rx.sring->rsp_prod;
+ rp = dev->rx.sring->rsp_prod;
rmb(); /* Ensure we see queued responses up to 'rp'. */
- cons = np->rx.rsp_cons;
+ cons = dev->rx.rsp_cons;
int nr_consumed=0;
while ((cons != rp))
@@ -87,7 +95,7 @@ moretodo:
struct net_buffer* buf;
unsigned char* page;
- rx = RING_GET_RESPONSE(&np->rx, cons);
+ rx = RING_GET_RESPONSE(&dev->rx, cons);
if (rx->flags & NETRXF_extra_info)
{
@@ -100,28 +108,26 @@ moretodo:
int id = rx->id;
- buf = &rx_buffers[id];
+ buf = &dev->rx_buffers[id];
page = (unsigned char*)buf->page;
gnttab_end_access(buf->gref);
if(rx->status>0)
{
- netif_rx(page+rx->offset,rx->status);
+ dev->netif_rx(page+rx->offset,rx->status);
}
- add_id_to_freelist(id,rx_freelist);
-
nr_consumed++;
++cons;
}
- np->rx.rsp_cons=rp;
+ dev->rx.rsp_cons=cons;
int more;
- RING_FINAL_CHECK_FOR_RESPONSES(&np->rx,more);
+ RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
if(more) goto moretodo;
- RING_IDX req_prod = np->rx.req_prod_pvt;
+ RING_IDX req_prod = dev->rx.req_prod_pvt;
int i;
netif_rx_request_t *req;
@@ -129,8 +135,8 @@ moretodo:
for(i=0; i<nr_consumed; i++)
{
int id = xennet_rxidx(req_prod + i);
- req = RING_GET_REQUEST(&np->rx, req_prod + i);
- struct net_buffer* buf = &rx_buffers[id];
+ req = RING_GET_REQUEST(&dev->rx, req_prod + i);
+ struct net_buffer* buf = &dev->rx_buffers[id];
void* page = buf->page;
/* We are sure to have free gnttab entries since they got released
above */
@@ -142,45 +148,44 @@ moretodo:
wmb();
- np->rx.req_prod_pvt = req_prod + i;
+ dev->rx.req_prod_pvt = req_prod + i;
int notify;
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
if (notify)
- notify_remote_via_evtchn(np->evtchn);
-
-}
-
-void network_tx_buf_gc(void)
+ notify_remote_via_evtchn(dev->evtchn);
+
+}
+
+void network_tx_buf_gc(struct netfront_dev *dev)
{
RING_IDX cons, prod;
unsigned short id;
- struct net_info *np = &net_info;
do {
- prod = np->tx.sring->rsp_prod;
+ prod = dev->tx.sring->rsp_prod;
rmb(); /* Ensure we see responses up to 'rp'. */
- for (cons = np->tx.rsp_cons; cons != prod; cons++)
+ for (cons = dev->tx.rsp_cons; cons != prod; cons++)
{
struct netif_tx_response *txrsp;
- txrsp = RING_GET_RESPONSE(&np->tx, cons);
+ txrsp = RING_GET_RESPONSE(&dev->tx, cons);
if (txrsp->status == NETIF_RSP_NULL)
continue;
id = txrsp->id;
- struct net_buffer* buf = &tx_buffers[id];
+ struct net_buffer* buf = &dev->tx_buffers[id];
gnttab_end_access(buf->gref);
buf->gref=GRANT_INVALID_REF;
- add_id_to_freelist(id,tx_freelist);
- up(&tx_sem);
+ add_id_to_freelist(id,dev->tx_freelist);
+ up(&dev->tx_sem);
}
- np->tx.rsp_cons = prod;
+ dev->tx.rsp_cons = prod;
/*
* Set a new event, then check for race with update of tx_cons.
@@ -190,10 +195,10 @@ void network_tx_buf_gc(void)
* data is outstanding: in such cases notification from Xen is
* likely to be the only kick that we'll get.
*/
- np->tx.sring->rsp_event =
- prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
+ dev->tx.sring->rsp_event =
+ prod + ((dev->tx.sring->req_prod - prod) >> 1) + 1;
mb();
- } while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
+ } while ((cons == prod) && (prod != dev->tx.sring->rsp_prod));
}
@@ -201,24 +206,21 @@ void netfront_handler(evtchn_port_t port
void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
{
int flags;
+ struct netfront_dev *dev = data;
local_irq_save(flags);
- network_tx_buf_gc();
- network_rx();
+ network_tx_buf_gc(dev);
+ network_rx(dev);
local_irq_restore(flags);
}
-char* backend;
-
-void init_netfront(void* si)
+struct netfront_dev *init_netfront(char *nodename, void
(*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6])
{
xenbus_transaction_t xbt;
- struct net_info* info = &net_info;
char* err;
char* message=NULL;
- char nodename[] = "device/vif/0";
struct netif_tx_sring *txs;
struct netif_rx_sring *rxs;
int retry=0;
@@ -226,18 +228,34 @@ void init_netfront(void* si)
char* mac;
char* msg;
- printk("************************ NETFRONT **********\n\n\n");
-
+ struct netfront_dev *dev;
+
+ if (!nodename)
+ nodename = "device/vif/0";
+
+ char path[strlen(nodename) + 1 + 10 + 1];
+
+ if (!thenetif_rx)
+ thenetif_rx = netif_rx;
+
+ printk("************************ NETFRONT for %s **********\n\n\n",
nodename);
+
+ dev = malloc(sizeof(*dev));
+ dev->nodename = strdup(nodename);
+
+ printk("net TX ring size %d\n", NET_TX_RING_SIZE);
+ printk("net RX ring size %d\n", NET_RX_RING_SIZE);
+ init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE);
for(i=0;i<NET_TX_RING_SIZE;i++)
{
- add_id_to_freelist(i,tx_freelist);
- tx_buffers[i].page = (char*)alloc_page();
+ add_id_to_freelist(i,dev->tx_freelist);
+ dev->tx_buffers[i].page = NULL;
}
for(i=0;i<NET_RX_RING_SIZE;i++)
{
- add_id_to_freelist(i,rx_freelist);
- rx_buffers[i].page = (char*)alloc_page();
+ /* TODO: that's a lot of memory */
+ dev->rx_buffers[i].page = (char*)alloc_page();
}
txs = (struct netif_tx_sring*) alloc_page();
@@ -248,20 +266,24 @@ void init_netfront(void* si)
SHARED_RING_INIT(txs);
SHARED_RING_INIT(rxs);
- FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
- FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
-
- info->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0);
- info->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0);
+ FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE);
+ FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE);
+
+ dev->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0);
+ dev->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0);
evtchn_alloc_unbound_t op;
op.dom = DOMID_SELF;
- op.remote_dom = 0;
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ op.remote_dom = xenbus_read_integer(path);
HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
clear_evtchn(op.port); /* Without, handler gets invoked now! */
- info->local_port = bind_evtchn(op.port, netfront_handler, NULL);
- info->evtchn=op.port;
-
+ dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
+ dev->evtchn=op.port;
+
+ dev->netif_rx = thenetif_rx;
+
+ // FIXME: proper frees on failures
again:
err = xenbus_transaction_start(&xbt);
if (err) {
@@ -269,19 +291,19 @@ again:
}
err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
- info->tx_ring_ref);
+ dev->tx_ring_ref);
if (err) {
message = "writing tx ring-ref";
goto abort_transaction;
}
err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
- info->rx_ring_ref);
+ dev->rx_ring_ref);
if (err) {
message = "writing rx ring-ref";
goto abort_transaction;
}
err = xenbus_printf(xbt, nodename,
- "event-channel", "%u", info->evtchn);
+ "event-channel", "%u", dev->evtchn);
if (err) {
message = "writing event-channel";
goto abort_transaction;
@@ -308,40 +330,45 @@ again:
abort_transaction:
xenbus_transaction_end(xbt, 1, &retry);
+ return NULL;
done:
- msg = xenbus_read(XBT_NIL, "device/vif/0/backend", &backend);
- msg = xenbus_read(XBT_NIL, "device/vif/0/mac", &mac);
-
- if ((backend == NULL) || (mac == NULL)) {
- struct evtchn_close op = { info->local_port };
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ snprintf(path, sizeof(path), "%s/mac", nodename);
+ msg = xenbus_read(XBT_NIL, path, &mac);
+
+ if ((dev->backend == NULL) || (mac == NULL)) {
+ struct evtchn_close op = { dev->local_port };
printk("%s: backend/mac failed\n", __func__);
- unbind_evtchn(info->local_port);
+ unbind_evtchn(dev->local_port);
HYPERVISOR_event_channel_op(EVTCHNOP_close, &op);
- return;
- }
-
- printk("backend at %s\n",backend);
+ return NULL;
+ }
+
+ printk("backend at %s\n",dev->backend);
printk("mac is %s\n",mac);
- char path[256];
- sprintf(path,"%s/state",backend);
-
- xenbus_watch_path(XBT_NIL, path);
-
- xenbus_wait_for_value(path,"4");
-
- //free(backend);
+ {
+ char path[strlen(dev->backend) + 1 + 5 + 1];
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path(XBT_NIL, path);
+
+ xenbus_wait_for_value(path,"4");
+
+ xenbus_unwatch_path(XBT_NIL, path);
+ }
printk("**************************\n");
- init_rx_buffers();
-
- unsigned char rawmac[6];
+ init_rx_buffers(dev);
+
/* Special conversion specifier 'hh' needed for __ia64__. Without
this mini-os panics with 'Unaligned reference'. */
- sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ if (rawmac)
+ sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&rawmac[0],
&rawmac[1],
&rawmac[2],
@@ -349,37 +376,35 @@ done:
&rawmac[4],
&rawmac[5]);
- net_app_main(si,rawmac);
-}
-
-void shutdown_netfront(void)
-{
- //xenbus_transaction_t xbt;
+ return dev;
+}
+
+void shutdown_netfront(struct netfront_dev *dev)
+{
char* err;
- char nodename[] = "device/vif/0";
-
- char path[256];
-
- printk("close network: backend at %s\n",backend);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6); /* closing */
- sprintf(path,"%s/state",backend);
-
+ char *nodename = dev->nodename;
+
+ char path[strlen(dev->backend) + 1 + 5 + 1];
+
+ printk("close network: backend at %s\n",dev->backend);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
+ xenbus_wait_for_value(path,"5");
+
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
xenbus_wait_for_value(path,"6");
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
-
- xenbus_wait_for_value(path,"2");
-
- unbind_all_ports();
-
- free(backend);
-}
-
-
-void init_rx_buffers(void)
-{
- struct net_info* np = &net_info;
+ unbind_evtchn(dev->local_port);
+
+ free(nodename);
+ free(dev->backend);
+ free(dev);
+}
+
+
+void init_rx_buffers(struct netfront_dev *dev)
+{
int i, requeue_idx;
netif_rx_request_t *req;
int notify;
@@ -387,8 +412,8 @@ void init_rx_buffers(void)
/* Rebuild the RX buffer freelist and the RX ring itself. */
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++)
{
- struct net_buffer* buf = &rx_buffers[requeue_idx];
- req = RING_GET_REQUEST(&np->rx, requeue_idx);
+ struct net_buffer* buf = &dev->rx_buffers[requeue_idx];
+ req = RING_GET_REQUEST(&dev->rx, requeue_idx);
buf->gref = req->gref =
gnttab_grant_access(0,virt_to_mfn(buf->page),0);
@@ -398,39 +423,40 @@ void init_rx_buffers(void)
requeue_idx++;
}
- np->rx.req_prod_pvt = requeue_idx;
-
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+ dev->rx.req_prod_pvt = requeue_idx;
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
if (notify)
- notify_remote_via_evtchn(np->evtchn);
-
- np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
-}
-
-
-void netfront_xmit(unsigned char* data,int len)
+ notify_remote_via_evtchn(dev->evtchn);
+
+ dev->rx.sring->rsp_event = dev->rx.rsp_cons + 1;
+}
+
+
+void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len)
{
int flags;
- struct net_info* info = &net_info;
struct netif_tx_request *tx;
RING_IDX i;
int notify;
- int id;
+ unsigned short id;
struct net_buffer* buf;
void* page;
- down(&tx_sem);
+ down(&dev->tx_sem);
local_irq_save(flags);
- id = get_id_from_freelist(tx_freelist);
+ id = get_id_from_freelist(dev->tx_freelist);
local_irq_restore(flags);
- buf = &tx_buffers[id];
+ buf = &dev->tx_buffers[id];
page = buf->page;
-
- i = info->tx.req_prod_pvt;
- tx = RING_GET_REQUEST(&info->tx, i);
+ if (!page)
+ page = buf->page = (char*) alloc_page();
+
+ i = dev->tx.req_prod_pvt;
+ tx = RING_GET_REQUEST(&dev->tx, i);
memcpy(page,data,len);
@@ -441,15 +467,15 @@ void netfront_xmit(unsigned char* data,i
tx->size = len;
tx->flags=0;
tx->id = id;
- info->tx.req_prod_pvt = i + 1;
+ dev->tx.req_prod_pvt = i + 1;
wmb();
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->tx, notify);
-
- if(notify) notify_remote_via_evtchn(info->evtchn);
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->tx, notify);
+
+ if(notify) notify_remote_via_evtchn(dev->evtchn);
local_irq_save(flags);
- network_tx_buf_gc();
+ network_tx_buf_gc(dev);
local_irq_restore(flags);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|