[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] minios: support several netfronts
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |