[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Switch network setup over to xenbus.
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID b402e77aac4674f938591dd718fb1259bb9e2100 # Parent d4ce28d819a8297ba3c82f3053c24ee125476dd5 Switch network setup over to xenbus. Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 24 22:22:11 2005 @@ -128,14 +128,6 @@ /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */ /* XXX SMH: yes it would :-( */ - -#ifdef CONFIG_XEN_NETDEV_FRONTEND - extern void netif_suspend(void); - extern void netif_resume(void); -#else -#define netif_suspend() do{}while(0) -#define netif_resume() do{}while(0) -#endif #ifdef CONFIG_XEN_USB_FRONTEND extern void usbif_resume(); @@ -218,8 +210,6 @@ kmem_cache_shrink(pgd_cache); #endif - netif_suspend(); - time_suspend(); #ifdef CONFIG_SMP @@ -276,8 +266,6 @@ #endif time_resume(); - - netif_resume(); usbif_resume(); diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/console/console.c --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Aug 24 22:22:11 2005 @@ -240,7 +240,11 @@ #endif /*** Useful function for console debugging -- goes straight to Xen. ***/ +#ifdef CONFIG_XEN_PRIVILEGED_GUEST asmlinkage int xprintk(const char *fmt, ...) +#else +asmlinkage int xprintk(const char *fmt, ...) +#endif { va_list args; int printk_len; diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Wed Aug 24 22:22:11 2005 @@ -1,2 +1,2 @@ -obj-y := netback.o control.o interface.o loopback.o +obj-y := netback.o xenbus.o interface.o loopback.o diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 24 22:22:11 2005 @@ -59,6 +59,7 @@ grant_ref_t rx_shmem_ref; #endif unsigned int evtchn; + unsigned int remote_evtchn; /* The shared rings and indexes. */ netif_tx_interface_t *tx; @@ -93,21 +94,26 @@ struct net_device *dev; struct net_device_stats stats; - struct work_struct work; + struct work_struct free_work; } netif_t; -void netif_create(netif_be_create_t *create); +int netif_create(netif_t *netif); void netif_destroy(netif_be_destroy_t *destroy); void netif_creditlimit(netif_be_creditlimit_t *creditlimit); -void netif_connect(netif_be_connect_t *connect); int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id); void netif_disconnect_complete(netif_t *netif); netif_t *netif_find_by_handle(domid_t domid, unsigned int handle); + +netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]); +void free_netif_callback(netif_t *netif); +int netif_map(netif_t *netif, unsigned long tx_ring_ref, + unsigned long rx_ring_ref, unsigned int evtchn); + #define netif_get(_b) (atomic_inc(&(_b)->refcnt)) #define netif_put(_b) \ do { \ if ( atomic_dec_and_test(&(_b)->refcnt) ) \ - netif_disconnect_complete(_b); \ + free_netif_callback(_b); \ } while (0) void netif_interface_init(void); diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 24 22:22:11 2005 @@ -9,10 +9,6 @@ #include "common.h" #include <linux/rtnetlink.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#endif - #define NETIF_HASHSZ 1024 #define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1)) @@ -66,87 +62,20 @@ return 0; } -static void __netif_disconnect_complete(void *arg) -{ - netif_t *netif = (netif_t *)arg; - ctrl_msg_t cmsg; - netif_be_disconnect_t disc; -#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX) - struct gnttab_unmap_grant_ref op; -#endif - - /* - * These can't be done in netif_disconnect() because at that point there - * may be outstanding requests in the network stack whose asynchronous - * responses must still be notified to the remote driver. - */ - -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - op.host_addr = netif->tx_shmem_vaddr; - op.handle = netif->tx_shmem_handle; - op.dev_bus_addr = 0; - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); -#endif - -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - op.host_addr = netif->rx_shmem_vaddr; - op.handle = netif->rx_shmem_handle; - op.dev_bus_addr = 0; - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); -#endif - - - vfree(netif->tx); /* Frees netif->rx as well. */ - - /* Construct the deferred response message. */ - cmsg.type = CMSG_NETIF_BE; - cmsg.subtype = CMSG_NETIF_BE_DISCONNECT; - cmsg.id = netif->disconnect_rspid; - cmsg.length = sizeof(netif_be_disconnect_t); - disc.domid = netif->domid; - disc.netif_handle = netif->handle; - disc.status = NETIF_BE_STATUS_OKAY; - memcpy(cmsg.msg, &disc, sizeof(disc)); - - /* - * Make sure message is constructed /before/ status change, because - * after the status change the 'netif' structure could be deallocated at - * any time. Also make sure we send the response /after/ status change, - * as otherwise a subsequent CONNECT request could spuriously fail if - * another CPU doesn't see the status change yet. - */ - mb(); - if ( netif->status != DISCONNECTING ) - BUG(); - netif->status = DISCONNECTED; - mb(); - - /* Send the successful response. */ - ctrl_if_send_response(&cmsg); -} - -void netif_disconnect_complete(netif_t *netif) -{ - INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif); - schedule_work(&netif->work); -} - -void netif_create(netif_be_create_t *create) -{ - int err = 0; - domid_t domid = create->domid; - unsigned int handle = create->netif_handle; +netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]) +{ + int err = 0, i; struct net_device *dev; - netif_t **pnetif, *netif; - char name[IFNAMSIZ] = {}; + netif_t **pnetif, *netif; + char name[IFNAMSIZ] = {}; snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle); dev = alloc_netdev(sizeof(netif_t), name, ether_setup); if ( dev == NULL ) { DPRINTK("Could not create netif: out of memory\n"); - create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - return; + // create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; + return NULL; } netif = netdev_priv(dev); @@ -167,9 +96,9 @@ if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) ) { DPRINTK("Could not create netif: already exists\n"); - create->status = NETIF_BE_STATUS_INTERFACE_EXISTS; + // create->status = NETIF_BE_STATUS_INTERFACE_EXISTS; free_netdev(dev); - return; + return NULL; } pnetif = &(*pnetif)->hash_next; } @@ -183,9 +112,10 @@ /* Disable queuing. */ dev->tx_queue_len = 0; - if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) && - (create->be_mac[2] == 0) && (create->be_mac[3] == 0) && - (create->be_mac[4] == 0) && (create->be_mac[5] == 0) ) + for (i = 0; i < ETH_ALEN; i++) + if (be_mac[i] != 0) + break; + if (i == ETH_ALEN) { /* * Initialise a dummy MAC address. We choose the numerically largest @@ -197,10 +127,8 @@ } else { - memcpy(dev->dev_addr, create->be_mac, ETH_ALEN); - } - - memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN); + memcpy(dev->dev_addr, be_mac, ETH_ALEN); + } rtnl_lock(); err = register_netdevice(dev); @@ -210,16 +138,187 @@ { DPRINTK("Could not register new net device %s: err=%d\n", dev->name, err); - create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; + // create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; free_netdev(dev); - return; + return NULL; } netif->hash_next = *pnetif; *pnetif = netif; DPRINTK("Successfully created netif\n"); - create->status = NETIF_BE_STATUS_OKAY; + // create->status = NETIF_BE_STATUS_OKAY; + return netif; +} + +static int map_frontend_page(netif_t *netif, unsigned long localaddr, + unsigned long tx_ring_ref, unsigned long rx_ring_ref) +{ +#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX) + pgprot_t prot = __pgprot(_KERNPG_TABLE); + int err; +#endif +#if defined(CONFIG_XEN_NETDEV_GRANT_TX) + { + struct gnttab_map_grant_ref op; + + /* Map: Use the Grant table reference */ + op.host_addr = localaddr; + op.flags = GNTMAP_host_map; + op.ref = tx_ring_ref; + op.dom = netif->domid; + + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Grant table operation failure !\n"); + return op.handle; + } + + netif->tx_shmem_ref = tx_ring_ref; + netif->tx_shmem_handle = op.handle; + netif->tx_shmem_vaddr = localaddr; + } +#else + err = direct_remap_area_pages(&init_mm, localaddr, + tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE, + prot, netif->domid); + if (err) + return err; +#endif + +#if defined(CONFIG_XEN_NETDEV_GRANT_RX) + { + struct gnttab_map_grant_ref op; + + /* Map: Use the Grant table reference */ + op.host_addr = localaddr + PAGE_SIZE; + op.flags = GNTMAP_host_map; + op.ref = rx_ring_ref; + op.dom = netif->domid; + + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Grant table operation failure !\n"); + return op.handle; + } + + netif->rx_shmem_ref = rx_ring_ref; + netif->rx_shmem_handle = op.handle; + netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; + } +#else + err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE, + rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE, + prot, netif->domid); + if (err) + return err; +#endif + + return 0; +} + +static void unmap_frontend_page(netif_t *netif) +{ +#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX) + struct gnttab_unmap_grant_ref op; +#endif + +#ifdef CONFIG_XEN_NETDEV_GRANT_TX + op.host_addr = netif->tx_shmem_vaddr; + op.handle = netif->tx_shmem_handle; + op.dev_bus_addr = 0; + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); +#endif + +#ifdef CONFIG_XEN_NETDEV_GRANT_RX + op.host_addr = netif->rx_shmem_vaddr; + op.handle = netif->rx_shmem_handle; + op.dev_bus_addr = 0; + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); +#endif +} + +int netif_map(netif_t *netif, unsigned long tx_ring_ref, + unsigned long rx_ring_ref, unsigned int evtchn) +{ + struct vm_struct *vma; + evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; + int err; + +#if 0 + if ( netif->status != DISCONNECTED ) { + connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED; + return; + } +#endif + + if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) { + // connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY; + return -ENOMEM; + } + + err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref, + rx_ring_ref); + if (err) { + vfree(vma->addr); + return err; + } + + op.u.bind_interdomain.dom1 = DOMID_SELF; + op.u.bind_interdomain.dom2 = netif->domid; + op.u.bind_interdomain.port1 = 0; + op.u.bind_interdomain.port2 = evtchn; + err = HYPERVISOR_event_channel_op(&op); + if (err) { + unmap_frontend_page(netif); + vfree(vma->addr); + return err; + } + + netif->evtchn = op.u.bind_interdomain.port1; + netif->remote_evtchn = evtchn; + + netif->tx_shmem_frame = tx_ring_ref; + netif->rx_shmem_frame = rx_ring_ref; + netif->tx = + (netif_tx_interface_t *)vma->addr; + netif->rx = + (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE); + netif->tx->resp_prod = netif->rx->resp_prod = 0; + netif_get(netif); + wmb(); /* Other CPUs see new state before interface is started. */ + + rtnl_lock(); + netif->status = CONNECTED; + wmb(); + if ( netif_running(netif->dev) ) + __netif_up(netif); + rtnl_unlock(); + + // connect->status = NETIF_BE_STATUS_OKAY; + return 0; +} + +static void free_netif(void *arg) +{ + netif_t *netif = (netif_t *)arg; + + /* + * These can't be done in netif_disconnect() because at that point there + * may be outstanding requests in the network stack whose asynchronous + * responses must still be notified to the remote driver. + */ + + unmap_frontend_page(netif); + vfree(netif->tx); /* Frees netif->rx as well. */ + + netif->status = DISCONNECTED; +} + +void free_netif_callback(netif_t *netif) +{ + INIT_WORK(&netif->free_work, free_netif, (void *)netif); + schedule_work(&netif->free_work); } void netif_destroy(netif_be_destroy_t *destroy) @@ -284,147 +383,6 @@ } creditlimit->status = NETIF_BE_STATUS_OKAY; -} - -void netif_connect(netif_be_connect_t *connect) -{ - domid_t domid = connect->domid; - unsigned int handle = connect->netif_handle; - unsigned int evtchn = connect->evtchn; - unsigned long tx_shmem_frame = connect->tx_shmem_frame; - unsigned long rx_shmem_frame = connect->rx_shmem_frame; - struct vm_struct *vma; -#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX) - pgprot_t prot = __pgprot(_KERNPG_TABLE); - int error; -#endif - netif_t *netif; - - netif = netif_find_by_handle(domid, handle); - if ( unlikely(netif == NULL) ) { - DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n", - connect->domid, connect->netif_handle); - connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND; - return; - } - - if ( netif->status != DISCONNECTED ) { - connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED; - return; - } - - if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) { - connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - return; - } - - -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) - { - struct gnttab_map_grant_ref op; - int tx_ref = connect->tx_shmem_ref; - - /* Map: Use the Grant table reference */ - op.host_addr = VMALLOC_VMADDR(vma->addr); - op.flags = GNTMAP_host_map; - op.ref = tx_ref; - op.dom = domid; - - if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) || - (op.handle < 0)) { - DPRINTK(" Grant table operation failure !\n"); - connect->status = NETIF_BE_STATUS_MAPPING_ERROR; - vfree(vma->addr); - return; - } - - netif->tx_shmem_ref = tx_ref; - netif->tx_shmem_handle = op.handle; - netif->tx_shmem_vaddr = VMALLOC_VMADDR(vma->addr); - } - - -#else - error = direct_remap_area_pages(&init_mm, - VMALLOC_VMADDR(vma->addr), - tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE, - prot, domid); - if ( error != 0 ) - { - if ( error == -ENOMEM ) - connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - else if ( error == -EFAULT ) - connect->status = NETIF_BE_STATUS_MAPPING_ERROR; - else - connect->status = NETIF_BE_STATUS_ERROR; - vfree(vma->addr); - return; - } -#endif - - -#if defined(CONFIG_XEN_NETDEV_GRANT_RX) - { - struct gnttab_map_grant_ref op; - int rx_ref = connect->rx_shmem_ref; - - - /* Map: Use the Grant table reference */ - op.host_addr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE; - op.flags = GNTMAP_host_map; - op.ref = rx_ref; - op.dom = domid; - - if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) || - (op.handle < 0)) { - DPRINTK(" Grant table operation failure !\n"); - connect->status = NETIF_BE_STATUS_MAPPING_ERROR; - vfree(vma->addr); - return; - } - - netif->rx_shmem_ref = rx_ref; - netif->rx_shmem_handle = handle; - netif->rx_shmem_vaddr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE; - } -#else - error = direct_remap_area_pages(&init_mm, - VMALLOC_VMADDR(vma->addr) + PAGE_SIZE, - rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE, - prot, domid); - if ( error != 0 ) - { - if ( error == -ENOMEM ) - connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - else if ( error == -EFAULT ) - connect->status = NETIF_BE_STATUS_MAPPING_ERROR; - else - connect->status = NETIF_BE_STATUS_ERROR; - vfree(vma->addr); - return; - } - -#endif - - netif->evtchn = evtchn; - netif->tx_shmem_frame = tx_shmem_frame; - netif->rx_shmem_frame = rx_shmem_frame; - netif->tx = - (netif_tx_interface_t *)vma->addr; - netif->rx = - (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE); - netif->tx->resp_prod = netif->rx->resp_prod = 0; - netif_get(netif); - wmb(); /* Other CPUs see new state before interface is started. */ - - rtnl_lock(); - netif->status = CONNECTED; - wmb(); - if ( netif_running(netif->dev) ) - __netif_up(netif); - rtnl_unlock(); - - connect->status = NETIF_BE_STATUS_OKAY; } int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id) diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 24 22:22:11 2005 @@ -987,7 +987,7 @@ spin_lock_init(&net_schedule_list_lock); INIT_LIST_HEAD(&net_schedule_list); - netif_ctrlif_init(); + netif_xenbus_init(); (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), netif_be_dbg, SA_SHIRQ, diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 24 22:22:11 2005 @@ -48,7 +48,7 @@ #include <asm/io.h> #include <asm/uaccess.h> #include <asm-xen/evtchn.h> -#include <asm-xen/ctrl_if.h> +#include <asm-xen/xenbus.h> #include <asm-xen/xen-public/io/netif.h> #include <asm-xen/balloon.h> #include <asm/page.h> @@ -112,7 +112,6 @@ #endif #if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) -static domid_t rdomid = 0; #define GRANT_INVALID_REF (0xFFFF) #endif @@ -135,10 +134,11 @@ static struct list_head dev_list; +#define netfront_info net_private struct net_private { struct list_head list; - struct net_device *dev; + struct net_device *netdev; struct net_device_stats stats; NETIF_RING_IDX rx_resp_cons, tx_resp_cons; @@ -176,6 +176,14 @@ */ struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; + + struct xenbus_device *xbdev; + char *backend; + int backend_id; + struct xenbus_watch watch; + int tx_ring_ref; + int rx_ring_ref; + u8 mac[ETH_ALEN]; }; /* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ @@ -187,13 +195,6 @@ (_list)[0] = (_list)[_id]; \ (unsigned short)_id; }) -static char *status_name[] = { - [NETIF_INTERFACE_STATUS_CLOSED] = "closed", - [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected", - [NETIF_INTERFACE_STATUS_CONNECTED] = "connected", - [NETIF_INTERFACE_STATUS_CHANGED] = "changed", -}; - static char *be_state_name[] = { [BEST_CLOSED] = "closed", [BEST_DISCONNECTED] = "disconnected", @@ -219,7 +220,7 @@ list_for_each (ent, &dev_list) { np = list_entry(ent, struct net_private, list); if (np->handle == handle) - return np->dev; + return np->netdev; } return NULL; } @@ -448,7 +449,7 @@ BUG(); } grant_rx_ref[id] = ref; - gnttab_grant_foreign_transfer_ref(ref, rdomid, + gnttab_grant_foreign_transfer_ref(ref, np->backend_id, virt_to_mfn(skb->head)); np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; #endif @@ -544,7 +545,7 @@ BUG(); } mfn = virt_to_mfn(skb->data); - gnttab_grant_foreign_access_ref(ref, rdomid, mfn, GNTMAP_readonly); + gnttab_grant_foreign_access_ref(ref, np->backend_id, mfn, GNTMAP_readonly); tx->addr = ref << PAGE_SHIFT; grant_tx_ref[id] = ref; #else @@ -809,7 +810,7 @@ { struct net_private *np = netdev_priv(dev); np->user_state = UST_CLOSED; - netif_stop_queue(np->dev); + netif_stop_queue(np->netdev); return 0; } @@ -821,8 +822,7 @@ } -static void network_connect(struct net_device *dev, - netif_fe_interface_status_t *status) +static void network_connect(struct net_device *dev) { struct net_private *np; int i, requeue_idx; @@ -890,7 +890,7 @@ */ np->backend_state = BEST_CONNECTED; wmb(); - notify_via_evtchn(status->evtchn); + notify_via_evtchn(np->evtchn); network_tx_buf_gc(dev); if (np->user_state == UST_OPEN) @@ -900,108 +900,57 @@ spin_unlock_irq(&np->tx_lock); } -static void vif_show(struct net_private *np) +static void show_device(struct net_private *np) { #ifdef DEBUG - if (np) { - IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n", - np->handle, - be_state_name[np->backend_state], - np->user_state ? "open" : "closed", - np->evtchn, - np->tx, - np->rx); - } else { - IPRINTK("<vif NULL>\n"); - } -#endif -} - -/* Send a connect message to xend to tell it to bring up the interface. */ -static void send_interface_connect(struct net_private *np) -{ - int err; - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT, - .length = sizeof(netif_fe_interface_connect_t), - }; - netif_fe_interface_connect_t *msg = (void*)cmsg.msg; - - msg->handle = np->handle; - msg->tx_shmem_frame = virt_to_mfn(np->tx); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - err = gnttab_grant_foreign_access(rdomid, msg->tx_shmem_frame, 0); - if (err < 0) { - printk(KERN_ALERT "#### netfront can't grant access to tx_shmem\n"); - BUG(); - } - msg->tx_shmem_ref = err; -#endif - - msg->rx_shmem_frame = virt_to_mfn(np->rx); -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - err = gnttab_grant_foreign_access(rdomid, msg->rx_shmem_frame, 0); - if (err < 0) { - printk(KERN_ALERT "#### netfront can't grant access to rx_shmem\n"); - BUG(); - } - msg->rx_shmem_ref = err; -#endif - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} - -/* Send a driver status notification to the domain controller. */ -static int send_driver_status(int ok) -{ - int err = 0; - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_DRIVER_STATUS, - .length = sizeof(netif_fe_driver_status_t), - }; - netif_fe_driver_status_t *msg = (void*)cmsg.msg; - - msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN); - err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); - return err; + if (np) { + IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n", + np->handle, + be_state_name[np->backend_state], + np->user_state ? "open" : "closed", + np->evtchn, + np->tx, + np->rx); + } else { + IPRINTK("<vif NULL>\n"); + } +#endif } /* Stop network device and free tx/rx queues and irq. */ -static void vif_release(struct net_private *np) -{ - /* Stop old i/f to prevent errors whilst we rebuild the state. */ - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - netif_stop_queue(np->dev); - /* np->backend_state = BEST_DISCONNECTED; */ - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); +static void shutdown_device(struct net_private *np) +{ + /* Stop old i/f to prevent errors whilst we rebuild the state. */ + spin_lock_irq(&np->tx_lock); + spin_lock(&np->rx_lock); + netif_stop_queue(np->netdev); + /* np->backend_state = BEST_DISCONNECTED; */ + spin_unlock(&np->rx_lock); + spin_unlock_irq(&np->tx_lock); - /* Free resources. */ - if ( np->tx != NULL ) - { - unbind_evtchn_from_irqhandler(np->evtchn, np->dev); - free_page((unsigned long)np->tx); - free_page((unsigned long)np->rx); - np->evtchn = 0; - np->tx = NULL; - np->rx = NULL; - } + /* Free resources. */ + if (np->tx) { + unbind_evtchn_from_irqhandler(np->evtchn, np->netdev); + np->evtchn = 0; + free_page((unsigned long)np->tx); + free_page((unsigned long)np->rx); + np->tx = NULL; + np->rx = NULL; + } } /* Release vif resources and close it down completely. */ static void vif_close(struct net_private *np) { + BUG(); WPRINTK("Unexpected netif-CLOSED message in state %s\n", be_state_name[np->backend_state]); - vif_release(np); + shutdown_device(np); np->backend_state = BEST_CLOSED; /* todo: take dev down and free. */ - vif_show(np); + show_device(np); } /* Move the vif into disconnected state. @@ -1010,6 +959,7 @@ */ static void vif_disconnect(struct net_private *np) { + BUG(); if(np->tx) free_page((unsigned long)np->tx); if(np->rx) free_page((unsigned long)np->rx); // Before this np->tx and np->rx had better be null. @@ -1018,8 +968,8 @@ memset(np->tx, 0, PAGE_SIZE); memset(np->rx, 0, PAGE_SIZE); np->backend_state = BEST_DISCONNECTED; - send_interface_connect(np); - vif_show(np); + // send_interface_connect(np); + show_device(np); } /* Begin interface recovery. @@ -1037,11 +987,12 @@ */ static void vif_reset(struct net_private *np) { + BUG(); IPRINTK("Attempting to reconnect network interface: handle=%u\n", np->handle); - vif_release(np); + shutdown_device(np); vif_disconnect(np); - vif_show(np); + show_device(np); } /* Move the vif into connected state. @@ -1049,20 +1000,17 @@ * Binds the irq to the event channel. */ static void -vif_connect(struct net_private *np, netif_fe_interface_status_t *status) -{ - struct net_device *dev = np->dev; - memcpy(dev->dev_addr, status->mac, ETH_ALEN); - network_connect(dev, status); - np->evtchn = status->evtchn; -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) - rdomid = status->domid; -#endif +connect_device(struct net_private *np, unsigned int evtchn) +{ + struct net_device *dev = np->netdev; + memcpy(dev->dev_addr, np->mac, ETH_ALEN); + np->evtchn = evtchn; + network_connect(dev); (void)bind_evtchn_to_irqhandler( np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); netctrl_connected_count(); (void)send_fake_arp(dev); - vif_show(np); + show_device(np); } static struct ethtool_ops network_ethtool_ops = @@ -1076,22 +1024,24 @@ * @param val return parameter for created device * @return 0 on success, error code otherwise */ -static int create_netdev(int handle, struct net_device **val) +static int create_netdev(int handle, struct xenbus_device *dev, + struct net_device **val) { int i, err = 0; - struct net_device *dev = NULL; + struct net_device *netdev = NULL; struct net_private *np = NULL; - if ((dev = alloc_etherdev(sizeof(struct net_private))) == NULL) { + if ((netdev = alloc_etherdev(sizeof(struct net_private))) == NULL) { printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__); err = -ENOMEM; goto exit; } - np = netdev_priv(dev); + np = netdev_priv(netdev); np->backend_state = BEST_CLOSED; np->user_state = UST_CLOSED; np->handle = handle; + np->xbdev = dev; spin_lock_init(&np->tx_lock); spin_lock_init(&np->rx_lock); @@ -1115,149 +1065,53 @@ #endif } - dev->open = network_open; - dev->hard_start_xmit = network_start_xmit; - dev->stop = network_close; - dev->get_stats = network_get_stats; - dev->poll = netif_poll; - dev->weight = 64; - dev->features = NETIF_F_IP_CSUM; - - SET_ETHTOOL_OPS(dev, &network_ethtool_ops); - - if ((err = register_netdev(dev)) != 0) { + netdev->open = network_open; + netdev->hard_start_xmit = network_start_xmit; + netdev->stop = network_close; + netdev->get_stats = network_get_stats; + netdev->poll = netif_poll; + netdev->weight = 64; + netdev->features = NETIF_F_IP_CSUM; + + SET_ETHTOOL_OPS(netdev, &network_ethtool_ops); + + if ((err = register_netdev(netdev)) != 0) { printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err); goto exit; } - if ((err = xennet_proc_addif(dev)) != 0) { - unregister_netdev(dev); + if ((err = xennet_proc_addif(netdev)) != 0) { + unregister_netdev(netdev); goto exit; } - np->dev = dev; + np->netdev = netdev; list_add(&np->list, &dev_list); exit: - if ((err != 0) && (dev != NULL)) - kfree(dev); + if ((err != 0) && (netdev != NULL)) + kfree(netdev); else if (val != NULL) - *val = dev; + *val = netdev; return err; } -/* Get the target interface for a status message. - * Creates the interface when it makes sense. - * The returned interface may be null when there is no error. - * - * @param status status message - * @param np return parameter for interface state - * @return 0 on success, error code otherwise - */ -static int -target_vif(netif_fe_interface_status_t *status, struct net_private **np) -{ - int err = 0; - struct net_device *dev; - - DPRINTK("> handle=%d\n", status->handle); - if (status->handle < 0) { - err = -EINVAL; - goto exit; - } - - if ((dev = find_dev_by_handle(status->handle)) != NULL) - goto exit; - - if (status->status == NETIF_INTERFACE_STATUS_CLOSED) - goto exit; - if (status->status == NETIF_INTERFACE_STATUS_CHANGED) - goto exit; - - /* It's a new interface in a good state - create it. */ - DPRINTK("> create device...\n"); - if ((err = create_netdev(status->handle, &dev)) != 0) - goto exit; - - netctrl.interface_n++; - - exit: - if (np != NULL) - *np = ((dev && !err) ? netdev_priv(dev) : NULL); - DPRINTK("< err=%d\n", err); - return err; -} - -/* Handle an interface status message. */ -static void netif_interface_status(netif_fe_interface_status_t *status) -{ - int err = 0; - struct net_private *np = NULL; - - DPRINTK("> status=%s handle=%d\n", - status_name[status->status], status->handle); - - if ((err = target_vif(status, &np)) != 0) { - WPRINTK("Invalid netif: handle=%u\n", status->handle); - return; - } - - if (np == NULL) { - DPRINTK("> no vif\n"); - return; - } - - switch (status->status) { - case NETIF_INTERFACE_STATUS_CLOSED: - switch (np->backend_state) { - case BEST_CLOSED: - case BEST_DISCONNECTED: - case BEST_CONNECTED: - vif_close(np); - break; - } - break; - - case NETIF_INTERFACE_STATUS_DISCONNECTED: - switch (np->backend_state) { - case BEST_CLOSED: - vif_disconnect(np); - break; - case BEST_DISCONNECTED: - case BEST_CONNECTED: - vif_reset(np); - break; - } - break; - - case NETIF_INTERFACE_STATUS_CONNECTED: - switch (np->backend_state) { - case BEST_CLOSED: - WPRINTK("Unexpected netif status %s in state %s\n", - status_name[status->status], - be_state_name[np->backend_state]); - vif_disconnect(np); - vif_connect(np, status); - break; - case BEST_DISCONNECTED: - vif_connect(np, status); - break; - } - break; - - case NETIF_INTERFACE_STATUS_CHANGED: - /* - * The domain controller is notifying us that a device has been - * added or removed. - */ - break; - - default: - WPRINTK("Invalid netif status code %d\n", status->status); - break; - } - - vif_show(np); +static int destroy_netdev(struct net_device *netdev) +{ + struct net_private *np = NULL; + +#ifdef CONFIG_PROC_FS + xennet_proc_delif(netdev); +#endif + + unregister_netdev(netdev); + + np = netdev_priv(netdev); + list_del(&np->list); + + kfree(netdev); + + return 0; } /* @@ -1268,115 +1122,6 @@ netctrl.up = status->status; netctrl_connected_count(); } - -/* Receive handler for control messages. */ -static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - - switch (msg->subtype) { - case CMSG_NETIF_FE_INTERFACE_STATUS: - netif_interface_status((netif_fe_interface_status_t *) &msg->msg[0]); - break; - - case CMSG_NETIF_FE_DRIVER_STATUS: - netif_driver_status((netif_fe_driver_status_t *) &msg->msg[0]); - break; - - default: - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); -} - - -#if 1 -/* Wait for all interfaces to be connected. - * - * This works OK, but we'd like to use the probing mode (see below). - */ -static int probe_interfaces(void) -{ - int err = 0, conn = 0; - int wait_i, wait_n = 100; - - DPRINTK(">\n"); - - for (wait_i = 0; wait_i < wait_n; wait_i++) { - DPRINTK("> wait_i=%d\n", wait_i); - conn = netctrl_connected(); - if(conn) break; - DPRINTK("> schedule_timeout...\n"); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); - } - - DPRINTK("> wait finished...\n"); - if (conn <= 0) { - err = netctrl_err(-ENETDOWN); - WPRINTK("Failed to connect all virtual interfaces: err=%d\n", err); - } - - DPRINTK("< err=%d\n", err); - - return err; -} -#else -/* Probe for interfaces until no more are found. - * - * This is the mode we'd like to use, but at the moment it panics the kernel. -*/ -static int probe_interfaces(void) -{ - int err = 0; - int wait_i, wait_n = 100; - ctrl_msg_t cmsg = { - .type = CMSG_NETIF_FE, - .subtype = CMSG_NETIF_FE_INTERFACE_STATUS, - .length = sizeof(netif_fe_interface_status_t), - }; - netif_fe_interface_status_t msg = {}; - ctrl_msg_t rmsg = {}; - netif_fe_interface_status_t *reply = (void*)rmsg.msg; - int state = TASK_UNINTERRUPTIBLE; - u32 query = -1; - - DPRINTK(">\n"); - - netctrl.interface_n = 0; - for (wait_i = 0; wait_i < wait_n; wait_i++) { - DPRINTK("> wait_i=%d query=%d\n", wait_i, query); - msg.handle = query; - memcpy(cmsg.msg, &msg, sizeof(msg)); - DPRINTK("> set_current_state...\n"); - set_current_state(state); - DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); - DPRINTK("> sending...\n"); - err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state); - DPRINTK("> err=%d\n", err); - if(err) goto exit; - DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply); - if((int)reply->handle < 0) { - // No more interfaces. - break; - } - query = -reply->handle - 2; - DPRINTK(">netif_interface_status ...\n"); - netif_interface_status(reply); - } - - exit: - if (err) { - err = netctrl_err(-ENETDOWN); - WPRINTK("Connecting virtual network interfaces failed: err=%d\n", err); - } - - DPRINTK("< err=%d\n", err); - return err; -} - -#endif /* * We use this notifier to send out a fake ARP reply to reset switches and @@ -1395,7 +1140,7 @@ list_for_each (ent, &dev_list) { np = list_entry(ent, struct net_private, list); - if (np->dev == dev) + if (np->netdev == dev) (void)send_fake_arp(dev); } @@ -1409,67 +1154,317 @@ .priority = 0 }; -static int __init netif_init(void) -{ - int err = 0; - - if (xen_start_info.flags & SIF_INITDOMAIN) - return 0; +static struct xenbus_device_id netfront_ids[] = { + { "vif" }, + { "" } +}; + +static void watch_for_status(struct xenbus_watch *watch, const char *node) +{ +#if 0 + struct netfront_info *info; + unsigned int binfo; + unsigned long sectors, sector_size; + int err; + + info = container_of(watch, struct netfront_info, watch); + node += strlen(watch->node); + + /* FIXME: clean up when error on the other end. */ + if (info->connected == BLKIF_STATE_CONNECTED) + return; + + err = xenbus_gather(watch->node, + "sectors", "%lu", §ors, + "info", "%u", &binfo, + "sector-size", "%lu", §or_size, + NULL); + if (err) { + xenbus_dev_error(info->xbdev, err, "reading backend fields"); + return; + } + + xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); + info->connected = BLKIF_STATE_CONNECTED; + + blkif_state = BLKIF_STATE_CONNECTED; + + xenbus_dev_ok(info->xbdev); + + /* Kick pending requests. */ + spin_lock_irq(&blkif_io_lock); + kick_pending_request_queues(info); + spin_unlock_irq(&blkif_io_lock); +#endif +} + +static int setup_device(struct xenbus_device *dev, struct netfront_info *info) +{ + evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound }; + int err; + #ifdef CONFIG_XEN_NETDEV_GRANT_TX - /* A grant for every ring slot */ - if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, - &gref_tx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); - return 1; - } - printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n"); + info->tx_ring_ref = GRANT_INVALID_REF; #endif #ifdef CONFIG_XEN_NETDEV_GRANT_RX - /* A grant for every ring slot */ - if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, - &gref_rx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); - return 1; - } - printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n"); -#endif - - if ((err = xennet_proc_init()) != 0) - return err; - - IPRINTK("Initialising virtual ethernet driver.\n"); - INIT_LIST_HEAD(&dev_list); - (void)register_inetaddr_notifier(¬ifier_inetdev); - netctrl_init(); - (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - send_driver_status(1); - err = probe_interfaces(); - if (err) - ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx); - - DPRINTK("< err=%d\n", err); - return err; -} - -static void netif_exit(void) -{ + info->rx_ring_ref = GRANT_INVALID_REF; +#endif + + info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); + if (info->tx == 0) { + err = -ENOMEM; + xenbus_dev_error(dev, err, "allocating tx ring page"); + goto out; + } + info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL); + if (info->rx == 0) { + err = -ENOMEM; + xenbus_dev_error(dev, err, "allocating rx ring page"); + goto out; + } + memset(info->tx, 0, PAGE_SIZE); + memset(info->rx, 0, PAGE_SIZE); + info->backend_state = BEST_DISCONNECTED; + #ifdef CONFIG_XEN_NETDEV_GRANT_TX - gnttab_free_grant_references(gref_tx_head); -#endif + err = gnttab_grant_foreign_access(info->backend_id, + virt_to_mfn(info->tx), 0); + if (err < 0) { + xenbus_dev_error(dev, err, "granting access to tx ring page"); + goto out; + } + info->tx_ring_ref = err; +#else + info->tx_ring_ref = virt_to_mfn(info->tx); +#endif + #ifdef CONFIG_XEN_NETDEV_GRANT_RX - gnttab_free_grant_references(gref_rx_head); -#endif -} - -static void vif_suspend(struct net_private *np) -{ + err = gnttab_grant_foreign_access(info->backend_id, + virt_to_mfn(info->rx), 0); + if (err < 0) { + xenbus_dev_error(dev, err, "granting access to rx ring page"); + goto out; + } + info->rx_ring_ref = err; +#else + info->rx_ring_ref = virt_to_mfn(info->rx); +#endif + + op.u.alloc_unbound.dom = info->backend_id; + err = HYPERVISOR_event_channel_op(&op); + if (err) { + xenbus_dev_error(dev, err, "allocating event channel"); + goto out; + } + connect_device(info, op.u.alloc_unbound.port); + return 0; + + out: + if (info->tx) + free_page((unsigned long)info->tx); + info->tx = 0; + if (info->rx) + free_page((unsigned long)info->rx); + info->rx = 0; +#ifdef CONFIG_XEN_NETDEV_GRANT_TX + if (info->tx_ring_ref != GRANT_INVALID_REF) + gnttab_end_foreign_access(info->tx_ring_ref, 0); + info->tx_ring_ref = GRANT_INVALID_REF; +#endif +#ifdef CONFIG_XEN_NETDEV_GRANT_RX + if (info->rx_ring_ref != GRANT_INVALID_REF) + gnttab_end_foreign_access(info->rx_ring_ref, 0); + info->rx_ring_ref = GRANT_INVALID_REF; +#endif + return err; +} + +/* Common code used when first setting up, and when resuming. */ +static int talk_to_backend(struct xenbus_device *dev, + struct netfront_info *info) +{ + char *backend, *mac, *e, *s; + const char *message; + int err, i; + + backend = NULL; + err = xenbus_gather(dev->nodename, + "backend-id", "%i", &info->backend_id, + "backend", NULL, &backend, + NULL); + if (XENBUS_EXIST_ERR(err)) + goto out; + if (backend && strlen(backend) == 0) { + err = -ENOENT; + goto out; + } + if (err < 0) { + xenbus_dev_error(dev, err, "reading %s/backend or backend-id", + dev->nodename); + goto out; + } + + mac = xenbus_read(dev->nodename, "mac", NULL); + if (IS_ERR(mac)) { + err = PTR_ERR(mac); + xenbus_dev_error(dev, err, "reading %s/mac", + dev->nodename); + goto out; + } + s = mac; + for (i = 0; i < ETH_ALEN; i++) { + info->mac[i] = simple_strtoul(s, &e, 16); + if (s == e || (e[0] != ':' && e[0] != 0)) { + kfree(mac); + err = -ENOENT; + xenbus_dev_error(dev, err, "parsing %s/mac", + dev->nodename); + goto out; + } + s = &e[1]; + } + kfree(mac); + + /* Create shared ring, alloc event channel. */ + err = setup_device(dev, info); + if (err) { + xenbus_dev_error(dev, err, "setting up ring"); + goto out; + } + + err = xenbus_transaction_start(dev->nodename); + if (err) { + xenbus_dev_error(dev, err, "starting transaction"); + goto destroy_ring; + } + + err = xenbus_printf(dev->nodename, "tx-ring-ref","%u", + info->tx_ring_ref); + if (err) { + message = "writing tx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(dev->nodename, "rx-ring-ref","%u", + info->rx_ring_ref); + if (err) { + message = "writing rx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(dev->nodename, + "event-channel", "%u", info->evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + + info->backend = backend; + backend = NULL; + + info->watch.node = info->backend; + info->watch.callback = watch_for_status; + err = register_xenbus_watch(&info->watch); + if (err) { + message = "registering watch on backend"; + goto abort_transaction; + } + + err = xenbus_transaction_end(0); + if (err) { + xenbus_dev_error(dev, err, "completing transaction"); + goto destroy_ring; + } + + out: + if (backend) + kfree(backend); + return err; + + abort_transaction: + xenbus_transaction_end(1); + /* Have to do this *outside* transaction. */ + xenbus_dev_error(dev, err, "%s", message); + destroy_ring: + shutdown_device(info); + goto out; +} + +/* Setup supplies the backend dir, virtual device. + + We place an event channel and shared frame entries. + We watch backend to wait if it's ok. */ +static int netfront_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err; + struct net_device *netdev; + unsigned int handle; + + printk("netfront_probe %p\n", dev); + err = xenbus_scanf(dev->nodename, "handle", "%u", &handle); + if (XENBUS_EXIST_ERR(err)) + return err; + if (err < 0) { + xenbus_dev_error(dev, err, "reading handle"); + return err; + } + + printk("netfront_probe handle %d\n", handle); + netdev = find_dev_by_handle(handle); + printk("netfront_probe found netdev %p\n", netdev); + if (netdev) + return 0; + + err = create_netdev(handle, dev, &netdev); + if (err) { + xenbus_dev_error(dev, err, "creating netdev"); + return err; + } + + printk("netfront_probe netdev %p\n", netdev); + err = talk_to_backend(dev, netdev_priv(netdev)); + if (err) { + destroy_netdev(netdev); + return err; + } + +#if 0 + /* Call once in case entries already there. */ + watch_for_status(&info->watch, info->watch.node); +#endif + return 0; +} + +static int netfront_remove(struct xenbus_device *dev) +{ + struct netfront_info *info = dev->data; + +#if 0 + if (info->backend) + unregister_xenbus_watch(&info->watch); + + if (info->mi) + xlvbd_del(info); + + blkif_free(info); + + kfree(info->backend); +#endif + kfree(info); + + return 0; +} + +static int netfront_suspend(struct xenbus_device *dev) +{ + struct net_private *np = dev->data; /* Avoid having tx/rx stuff happen until we're ready. */ - unbind_evtchn_from_irqhandler(np->evtchn, np->dev); -} - -static void vif_resume(struct net_private *np) -{ + unbind_evtchn_from_irqhandler(np->evtchn, np->netdev); + return 0; +} + +static int netfront_resume(struct xenbus_device *dev) +{ + struct net_private *np = dev->data; /* * Connect regardless of whether IFF_UP flag set. * Stop bad things from happening until we're back up. @@ -1478,29 +1473,101 @@ memset(np->tx, 0, PAGE_SIZE); memset(np->rx, 0, PAGE_SIZE); - send_interface_connect(np); -} - -void netif_suspend(void) -{ - struct list_head *ent; - struct net_private *np; - - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - vif_suspend(np); - } -} - -void netif_resume(void) -{ - struct list_head *ent; - struct net_private *np; - - list_for_each (ent, &dev_list) { - np = list_entry(ent, struct net_private, list); - vif_resume(np); - } + // send_interface_connect(np); + return 0; +} + +static struct xenbus_driver netfront = { + .name = "vif", + .owner = THIS_MODULE, + .ids = netfront_ids, + .probe = netfront_probe, + .remove = netfront_remove, + .resume = netfront_resume, + .suspend = netfront_suspend, +}; + +static void __init init_net_xenbus(void) +{ + xenbus_register_device(&netfront); +} + +static int wait_for_netif(void) +{ + int err = 0, conn = 0; + int i; + + /* + * We should figure out how many and which devices we need to + * proceed and only wait for those. For now, continue once the + * first device is around. + */ + for ( i=0; i < 10*HZ; i++ ) + { + conn = netctrl_connected(); + if (conn) + break; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + if (conn <= 0) { + err = netctrl_err(-ENETDOWN); + WPRINTK("Timeout connecting to device!\n"); + } + return err; +} + +static int __init netif_init(void) +{ + int err = 0; + + if (xen_start_info.flags & SIF_INITDOMAIN) + return 0; + +#ifdef CONFIG_XEN_NETDEV_GRANT_TX + /* A grant for every ring slot */ + if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, + &gref_tx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); + return 1; + } + printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n"); +#endif +#ifdef CONFIG_XEN_NETDEV_GRANT_RX + /* A grant for every ring slot */ + if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, + &gref_rx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); + return 1; + } + printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n"); +#endif + + if ((err = xennet_proc_init()) != 0) + return err; + + IPRINTK("Initialising virtual ethernet driver.\n"); + + INIT_LIST_HEAD(&dev_list); + (void)register_inetaddr_notifier(¬ifier_inetdev); + netctrl_init(); + + init_net_xenbus(); + + wait_for_netif(); + + return err; +} + +static void netif_exit(void) +{ +#ifdef CONFIG_XEN_NETDEV_GRANT_TX + gnttab_free_grant_references(gref_tx_head); +#endif +#ifdef CONFIG_XEN_NETDEV_GRANT_RX + gnttab_free_grant_references(gref_rx_head); +#endif } #ifdef CONFIG_PROC_FS diff -r d4ce28d819a8 -r b402e77aac46 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Wed Aug 24 22:21:24 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Wed Aug 24 22:22:11 2005 @@ -265,6 +265,8 @@ self.info = None self.blkif_backend = False self.netif_backend = False + self.netif_idx = 0 + #todo: state: running, suspended self.state = STATE_VM_OK self.state_updated = threading.Condition() @@ -400,8 +402,7 @@ db['virtual-device'] = "%i" % devnum #db['backend'] = sxp.child_value(devconfig, 'backend', '0') db['backend'] = backdb.getPath() - db['backend-id'] = "%i" % int(sxp.child_value(devconfig, - 'backend', '0')) + db['backend-id'] = "%i" % backdom.id backdb['frontend'] = db.getPath() (type, params) = string.split(sxp.child_value(devconfig, 'uname'), ':', 1) @@ -417,6 +418,37 @@ db.saveDB(save=True) return + + if type == 'vif': + backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) + + log.error(devconfig) + + devnum = self.netif_idx + self.netif_idx += 1 + + # create backend db + backdb = backdom.db.addChild("/backend/%s/%s/%d" % + (type, self.uuid, devnum)) + + # create frontend db + db = self.db.addChild("/device/%s/%d" % (type, devnum)) + + backdb['frontend'] = db.getPath() + backdb['frontend-id'] = "%i" % self.id + backdb['handle'] = "%i" % devnum + backdb.saveDB(save=True) + + db['backend'] = backdb.getPath() + db['backend-id'] = "%i" % backdom.id + db['handle'] = "%i" % devnum + log.error(sxp.child_value(devconfig, 'mac')) + db['mac'] = sxp.child_value(devconfig, 'mac') + + db.saveDB(save=True) + + return + ctrl = self.findDeviceController(type) return ctrl.createDevice(devconfig, recreate=self.recreate, change=change) diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- /dev/null Wed Aug 24 22:21:24 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Aug 24 22:22:11 2005 @@ -0,0 +1,323 @@ +/* Xenbus code for netif backend + Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <stdarg.h> +#include <linux/module.h> +#include <asm-xen/xenbus.h> +#include "common.h" + +struct backend_info +{ + struct xenbus_device *dev; + + /* our communications channel */ + netif_t *netif; + + long int frontend_id; +#if 0 + long int pdev; + long int readonly; +#endif + + /* watch back end for changes */ + struct xenbus_watch backend_watch; + + /* watch front end for changes */ + struct xenbus_watch watch; + char *frontpath; +}; + +static int netback_remove(struct xenbus_device *dev) +{ + struct backend_info *be = dev->data; + + if (be->watch.node) + unregister_xenbus_watch(&be->watch); + unregister_xenbus_watch(&be->backend_watch); +#if 0 + if (be->blkif) + blkif_put(be->blkif); +#endif + if (be->frontpath) + kfree(be->frontpath); + kfree(be); + return 0; +} + +/* Front end tells us frame. */ +static void frontend_changed(struct xenbus_watch *watch, const char *node) +{ + unsigned long tx_ring_ref, rx_ring_ref; + unsigned int evtchn; + int err; + struct backend_info *be + = container_of(watch, struct backend_info, watch); + char *mac, *e, *s; + int i; + + /* If other end is gone, delete ourself. */ + if (node && !xenbus_exists(be->frontpath, "")) { + xenbus_rm(be->dev->nodename, ""); + device_unregister(&be->dev->dev); + return; + } + if (be->netif == NULL || be->netif->status == CONNECTED) + return; + + mac = xenbus_read(be->frontpath, "mac", NULL); + if (IS_ERR(mac)) { + err = PTR_ERR(mac); + xenbus_dev_error(be->dev, err, "reading %s/mac", + be->dev->nodename); + return; + } + s = mac; + for (i = 0; i < ETH_ALEN; i++) { + be->netif->fe_dev_addr[i] = simple_strtoul(s, &e, 16); + if (s == e || (e[0] != ':' && e[0] != 0)) { + kfree(mac); + err = -ENOENT; + xenbus_dev_error(be->dev, err, "parsing %s/mac", + be->dev->nodename); + return; + } + s = &e[1]; + } + kfree(mac); + + err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref, + "rx-ring-ref", "%lu", &rx_ring_ref, + "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_error(be->dev, err, + "reading %s/ring-ref and event-channel", + be->frontpath); + return; + } + +#if 0 + /* Supply the information about the device the frontend needs */ + err = xenbus_transaction_start(be->dev->nodename); + if (err) { + xenbus_dev_error(be->dev, err, "starting transaction"); + return; + } + + err = xenbus_printf(be->dev->nodename, "sectors", "%lu", + vbd_size(&be->blkif->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/sectors", + be->dev->nodename); + goto abort; + } + + /* FIXME: use a typename instead */ + err = xenbus_printf(be->dev->nodename, "info", "%u", + vbd_info(&be->blkif->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/info", + be->dev->nodename); + goto abort; + } + err = xenbus_printf(be->dev->nodename, "sector-size", "%lu", + vbd_secsize(&be->blkif->vbd)); + if (err) { + xenbus_dev_error(be->dev, err, "writing %s/sector-size", + be->dev->nodename); + goto abort; + } +#endif + + /* Map the shared frame, irq etc. */ + err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn); + if (err) { + xenbus_dev_error(be->dev, err, + "mapping shared-frames %lu/%lu port %u", + tx_ring_ref, rx_ring_ref, evtchn); + goto abort; + } + +#if 0 + xenbus_transaction_end(0); +#endif + xenbus_dev_ok(be->dev); + + return; + +abort: + // xenbus_transaction_end(1); + ; +} + +/* + Setup supplies physical device. + We provide event channel and device details to front end. + Frontend supplies shared frame and event channel. + */ +static void backend_changed(struct xenbus_watch *watch, const char *node) +{ + int err; + char *p; + long int handle, pdev; + struct backend_info *be + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; + + err = xenbus_scanf(dev->nodename, "handle", "%li", &handle); + if (XENBUS_EXIST_ERR(err)) + return; + if (err < 0) { + xenbus_dev_error(dev, err, "reading handle"); + return; + } + +#if 0 + err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev); + if (XENBUS_EXIST_ERR(err)) + return; + if (err < 0) { + xenbus_dev_error(dev, err, "reading physical-device"); + return; + } + if (be->pdev && be->pdev != pdev) { + printk(KERN_WARNING + "changing physical-device not supported\n"); + return; + } + be->pdev = pdev; + + /* If there's a read-only node, we're read only. */ + p = xenbus_read(dev->nodename, "read-only", NULL); + if (!IS_ERR(p)) { + be->readonly = 1; + kfree(p); + } +#endif + + if (be->netif == NULL) { + be->netif = alloc_netif(be->frontend_id, handle, be_mac); + if (IS_ERR(be->netif)) { + err = PTR_ERR(be->netif); + be->netif = NULL; + xenbus_dev_error(dev, err, "creating interface"); + return; + } + +#if 0 + err = vbd_create(be->netif, handle, be->pdev, be->readonly); + if (err) { + xenbus_dev_error(dev, err, "creating vbd structure"); + return; + } +#endif + + /* Pass in NULL node to skip exist test. */ + frontend_changed(&be->watch, NULL); + } +} + +static int netback_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + struct backend_info *be; + char *frontend; + int err; + + be = kmalloc(sizeof(*be), GFP_KERNEL); + if (!be) { + xenbus_dev_error(dev, -ENOMEM, "allocating backend structure"); + return -ENOMEM; + } + memset(be, 0, sizeof(*be)); + + frontend = NULL; + err = xenbus_gather(dev->nodename, + "frontend-id", "%li", &be->frontend_id, + "frontend", NULL, &frontend, + NULL); + if (XENBUS_EXIST_ERR(err)) + goto free_be; + if (err < 0) { + xenbus_dev_error(dev, err, + "reading %s/frontend or frontend-id", + dev->nodename); + goto free_be; + } + if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) { + /* If we can't get a frontend path and a frontend-id, + * then our bus-id is no longer valid and we need to + * destroy the backend device. + */ + err = -ENOENT; + goto free_be; + } + + be->dev = dev; + be->backend_watch.node = dev->nodename; + be->backend_watch.callback = backend_changed; + err = register_xenbus_watch(&be->backend_watch); + if (err) { + be->backend_watch.node = NULL; + xenbus_dev_error(dev, err, "adding backend watch on %s", + dev->nodename); + goto free_be; + } + + be->frontpath = frontend; + be->watch.node = be->frontpath; + be->watch.callback = frontend_changed; + err = register_xenbus_watch(&be->watch); + if (err) { + be->watch.node = NULL; + xenbus_dev_error(dev, err, + "adding frontend watch on %s", + be->frontpath); + goto free_be; + } + + dev->data = be; + + backend_changed(&be->backend_watch, dev->nodename); + return 0; + + free_be: + if (be->backend_watch.node) + unregister_xenbus_watch(&be->backend_watch); + if (frontend) + kfree(frontend); + kfree(be); + return err; +} + +static struct xenbus_device_id netback_ids[] = { + { "vif" }, + { "" } +}; + +static struct xenbus_driver netback = { + .name = "vif", + .owner = THIS_MODULE, + .ids = netback_ids, + .probe = netback_probe, + .remove = netback_remove, +}; + +void netif_xenbus_init(void) +{ + xenbus_register_backend(&netback); +} diff -r d4ce28d819a8 -r b402e77aac46 linux-2.6-xen-sparse/drivers/xen/netback/control.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/control.c Wed Aug 24 22:21:24 2005 +++ /dev/null Wed Aug 24 22:22:11 2005 @@ -1,58 +0,0 @@ -/****************************************************************************** - * arch/xen/drivers/netif/backend/control.c - * - * Routines for interfacing with the control plane. - * - * Copyright (c) 2004, Keir Fraser - */ - -#include "common.h" - -static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - DPRINTK("Received netif backend message, subtype=%d\n", msg->subtype); - - switch ( msg->subtype ) - { - case CMSG_NETIF_BE_CREATE: - netif_create((netif_be_create_t *)&msg->msg[0]); - break; - case CMSG_NETIF_BE_DESTROY: - netif_destroy((netif_be_destroy_t *)&msg->msg[0]); - break; - case CMSG_NETIF_BE_CREDITLIMIT: - netif_creditlimit((netif_be_creditlimit_t *)&msg->msg[0]); - break; - case CMSG_NETIF_BE_CONNECT: - netif_connect((netif_be_connect_t *)&msg->msg[0]); - break; - case CMSG_NETIF_BE_DISCONNECT: - if ( !netif_disconnect((netif_be_disconnect_t *)&msg->msg[0],msg->id) ) - return; /* Sending the response is deferred until later. */ - break; - default: - DPRINTK("Parse error while reading message subtype %d, len %d\n", - msg->subtype, msg->length); - msg->length = 0; - break; - } - - ctrl_if_send_response(msg); -} - -void netif_ctrlif_init(void) -{ - ctrl_msg_t cmsg; - netif_be_driver_status_t st; - - (void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - - /* Send a driver-UP notification to the domain controller. */ - cmsg.type = CMSG_NETIF_BE; - cmsg.subtype = CMSG_NETIF_BE_DRIVER_STATUS; - cmsg.length = sizeof(netif_be_driver_status_t); - st.status = NETIF_DRIVER_STATUS_UP; - memcpy(cmsg.msg, &st, sizeof(st)); - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |