bitkeeper revision 1.1108.7.1 (40fd3300BIfHRgHP5-DpQTLgUmNmEQ)
Merge http://xen.bkbits.net:8080/xeno-unstable.bk into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
No files matched your search
@@ -72,7 +72,6 @@
|
||||
4097ba837h2tuiweIWp-voNVzCRI6g linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c
|
||||
4087cf0d5dudKw_DecIJgOhLlBF_0Q linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c
|
||||
405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/Makefile
|
||||
405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c
|
||||
4097ba83Qy2eafeFUhGhm6_4iMIIDw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/netif.h
|
||||
3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.26-xen-sparse/arch/xen/kernel/Makefile
|
||||
4075806dE5mQwlVUf8-t3YXjiMMWDQ linux-2.4.26-xen-sparse/arch/xen/kernel/ctrl_if.c
|
||||
@@ -199,7 +198,7 @@
|
||||
40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.7-xen-sparse/drivers/xen/evtchn/evtchn.c
|
||||
40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.7-xen-sparse/drivers/xen/net/Kconfig
|
||||
40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.7-xen-sparse/drivers/xen/net/Makefile
|
||||
40f56239vUsbJCS9tGFfRVi1YZlGEg linux-2.6.7-xen-sparse/drivers/xen/net/network.c
|
||||
405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.7-xen-sparse/drivers/xen/net/network.c
|
||||
40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/desc.h
|
||||
40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h
|
||||
40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h
|
||||
@@ -366,6 +365,33 @@
|
||||
40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py
|
||||
40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
|
||||
40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py
|
||||
40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/xend/sv/DomInfo.py
|
||||
40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/xend/sv/DomList.py
|
||||
40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/xend/sv/GenTabbed.py
|
||||
40fcefb2QZAn3u3sX-M7NXBjOv5HGg tools/python/xen/xend/sv/HTMLBase.py
|
||||
40fcefb2vnfDbl4w_yCTedROPuqs0g tools/python/xen/xend/sv/Main.py
|
||||
40fcefb2K1xqVVT4D-p7nL2GzS4scg tools/python/xen/xend/sv/Main.rpy
|
||||
40fcefb24h-04WaHag-Tg4nxWPhTig tools/python/xen/xend/sv/NodeInfo.py
|
||||
40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/xend/sv/TabView.py
|
||||
40fcefb23s0sQlDfl4sPP0Un8oZGhg tools/python/xen/xend/sv/XendClientDeferred.py
|
||||
40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/xend/sv/__init__.py
|
||||
40fcefb2Nhe-sT74KBB_3mYQg9Dl4Q tools/python/xen/xend/sv/images/internet copy.jpg
|
||||
40fcefb2QmVa4xdjdnSTXEdF2fZCDA tools/python/xen/xend/sv/images/internet.jpg
|
||||
40fcefb2g8Ez5jJIPHGN_KX7GtxV4w tools/python/xen/xend/sv/images/internet.psd
|
||||
40fcefb3wXQMsl9WkgQAVtdrupm4sw tools/python/xen/xend/sv/images/left-end-highlight.jpg
|
||||
40fcefb3K6ESt5sQhD9aCQRscQIlXQ tools/python/xen/xend/sv/images/left-end-no-highlight.jpg
|
||||
40fcefb3BUT98zPzW8kAFKuxGdh4XA tools/python/xen/xend/sv/images/middle-highlight.jpg
|
||||
40fcefb38OTgsUKHBpwshLLIsiIaCA tools/python/xen/xend/sv/images/middle-no-highlight.jpg
|
||||
40fcefb32SPtrw36c4S6YGFlLvkKuw tools/python/xen/xend/sv/images/orb_01.jpg
|
||||
40fcefb3Ok5qkX3iM7ZEPVkRInrUpg tools/python/xen/xend/sv/images/orb_02.jpg
|
||||
40fcefb3JnT5XeKTuVF4yUMGOtuNZg tools/python/xen/xend/sv/images/right-end-highlight.jpg
|
||||
40fcefb3-DuYOS7noo2W7b_0p7TOUg tools/python/xen/xend/sv/images/right-end-no-highlight.jpg
|
||||
40fcefb3qNbAZR5FYGPAZ9sFPVMTDA tools/python/xen/xend/sv/images/seperator-left-highlight.jpg
|
||||
40fcefb3dgsa24WLk_BJeYQHrDLuOg tools/python/xen/xend/sv/images/seperator-right-highlight.jpg
|
||||
40fcefb3FtiX4Pd2kT8wDlp8u8xRhQ tools/python/xen/xend/sv/images/seperator.jpg
|
||||
40fcefb3yMSrZvApO9ToIi-iQwnchA tools/python/xen/xend/sv/images/xen.png
|
||||
40fcefb3zGC9XNBkSwTEobCoq8YClA tools/python/xen/xend/sv/inc/style.css
|
||||
40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/xend/sv/util.py
|
||||
40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
|
||||
40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
|
||||
40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
|
||||
|
||||
@@ -93,7 +93,8 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
}
|
||||
|
||||
mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB;
|
||||
(void)HYPERVISOR_multicall(mcl, nr_pages);
|
||||
if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
|
||||
BUG();
|
||||
}
|
||||
|
||||
|
||||
@@ -402,7 +403,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
phys_seg[i].buffer >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
(void)HYPERVISOR_multicall(mcl, nr_psegs);
|
||||
if ( unlikely(HYPERVISOR_multicall(mcl, nr_psegs) != 0) )
|
||||
BUG();
|
||||
|
||||
for ( i = 0; i < nr_psegs; i++ )
|
||||
{
|
||||
|
||||
@@ -73,10 +73,7 @@ static void __refresh_mfn_list(void)
|
||||
int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation,
|
||||
mfn_list, MAX_MFN_ALLOC);
|
||||
if ( unlikely(ret != MAX_MFN_ALLOC) )
|
||||
{
|
||||
printk(KERN_ALERT "Unable to increase memory reservation (%d)\n", ret);
|
||||
BUG();
|
||||
}
|
||||
alloc_index = MAX_MFN_ALLOC;
|
||||
}
|
||||
|
||||
@@ -97,8 +94,8 @@ static void dealloc_mfn(unsigned long mfn)
|
||||
spin_lock_irqsave(&mfn_lock, flags);
|
||||
if ( alloc_index != MAX_MFN_ALLOC )
|
||||
mfn_list[alloc_index++] = mfn;
|
||||
else
|
||||
(void)HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, &mfn, 1);
|
||||
else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, &mfn, 1) != 1 )
|
||||
BUG();
|
||||
spin_unlock_irqrestore(&mfn_lock, flags);
|
||||
}
|
||||
|
||||
@@ -238,7 +235,8 @@ static void net_rx_action(unsigned long unused)
|
||||
return;
|
||||
|
||||
mcl[-2].args[2] = UVMF_FLUSH_TLB;
|
||||
(void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) )
|
||||
BUG();
|
||||
|
||||
mcl = rx_mcl;
|
||||
mmu = rx_mmu;
|
||||
@@ -252,31 +250,27 @@ static void net_rx_action(unsigned long unused)
|
||||
mdata = ((mmu[2].ptr & PAGE_MASK) |
|
||||
((unsigned long)skb->data & ~PAGE_MASK));
|
||||
|
||||
phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn;
|
||||
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
netif->stats.rx_bytes += size;
|
||||
netif->stats.rx_packets++;
|
||||
|
||||
/* The update_va_mapping() must not fail. */
|
||||
if ( unlikely(mcl[0].args[5] != 0) )
|
||||
BUG();
|
||||
|
||||
/* Check the reassignment error code. */
|
||||
status = NETIF_RSP_OKAY;
|
||||
if ( unlikely(mcl[1].args[5] != 0) )
|
||||
{
|
||||
DPRINTK("Failed MMU update transferring to DOM%u\n",
|
||||
netif->domid);
|
||||
(void)HYPERVISOR_update_va_mapping(
|
||||
(unsigned long)skb->head >> PAGE_SHIFT,
|
||||
(pte_t) { (mdata & PAGE_MASK) | __PAGE_KERNEL },
|
||||
UVMF_INVLPG);
|
||||
dealloc_mfn(new_mfn);
|
||||
DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
|
||||
dealloc_mfn(mdata >> PAGE_SHIFT);
|
||||
status = NETIF_RSP_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn;
|
||||
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
netif->stats.rx_bytes += size;
|
||||
netif->stats.rx_packets++;
|
||||
|
||||
status = NETIF_RSP_OKAY;
|
||||
}
|
||||
|
||||
evtchn = netif->evtchn;
|
||||
id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
|
||||
@@ -380,14 +374,15 @@ static void net_tx_action(unsigned long unused)
|
||||
NETIF_RING_IDX i;
|
||||
struct page *page;
|
||||
multicall_entry_t *mcl;
|
||||
PEND_RING_IDX dc, dp;
|
||||
|
||||
if ( (i = dealloc_cons) == dealloc_prod )
|
||||
if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
|
||||
goto skip_dealloc;
|
||||
|
||||
mcl = tx_mcl;
|
||||
while ( i != dealloc_prod )
|
||||
while ( dc != dp )
|
||||
{
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(i++)];
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
|
||||
mcl[0].op = __HYPERVISOR_update_va_mapping;
|
||||
mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
|
||||
mcl[0].args[1] = 0;
|
||||
@@ -396,10 +391,16 @@ static void net_tx_action(unsigned long unused)
|
||||
}
|
||||
|
||||
mcl[-1].args[2] = UVMF_FLUSH_TLB;
|
||||
(void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl);
|
||||
if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
|
||||
BUG();
|
||||
|
||||
while ( dealloc_cons != dealloc_prod )
|
||||
mcl = tx_mcl;
|
||||
while ( dealloc_cons != dp )
|
||||
{
|
||||
/* The update_va_mapping() must not fail. */
|
||||
if ( unlikely(mcl[0].args[5] != 0) )
|
||||
BUG();
|
||||
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
|
||||
|
||||
netif = pending_tx_info[pending_idx].netif;
|
||||
@@ -421,6 +422,8 @@ static void net_tx_action(unsigned long unused)
|
||||
add_to_net_schedule_list_tail(netif);
|
||||
|
||||
netif_put(netif);
|
||||
|
||||
mcl++;
|
||||
}
|
||||
|
||||
skip_dealloc:
|
||||
@@ -495,7 +498,7 @@ static void net_tx_action(unsigned long unused)
|
||||
|
||||
pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
|
||||
|
||||
if ( unlikely((skb = dev_alloc_skb(PKT_PROT_LEN)) == NULL) )
|
||||
if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) )
|
||||
{
|
||||
DPRINTK("Can't allocate a skb in start_xmit.\n");
|
||||
make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
|
||||
@@ -503,6 +506,9 @@ static void net_tx_action(unsigned long unused)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Packets passed to netif_rx() must have some headroom. */
|
||||
skb_reserve(skb, 16);
|
||||
|
||||
mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
|
||||
mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
|
||||
mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
|
||||
@@ -526,7 +532,8 @@ static void net_tx_action(unsigned long unused)
|
||||
if ( mcl == tx_mcl )
|
||||
return;
|
||||
|
||||
(void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl);
|
||||
if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
|
||||
BUG();
|
||||
|
||||
mcl = tx_mcl;
|
||||
while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
|
||||
|
||||
@@ -1,867 +0,0 @@
|
||||
/******************************************************************************
|
||||
* arch/xen/drivers/netif/frontend/main.c
|
||||
*
|
||||
* Virtual network driver for conversing with remote driver backends.
|
||||
*
|
||||
* Copyright (c) 2002-2004, K A Fraser
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#include <asm/evtchn.h>
|
||||
#include <asm/ctrl_if.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#include "../netif.h"
|
||||
|
||||
#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
|
||||
|
||||
static void network_tx_buf_gc(struct net_device *dev);
|
||||
static void network_alloc_rx_buffers(struct net_device *dev);
|
||||
|
||||
static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE];
|
||||
static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1];
|
||||
static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
|
||||
|
||||
static struct list_head dev_list;
|
||||
|
||||
struct net_private
|
||||
{
|
||||
struct list_head list;
|
||||
struct net_device *dev;
|
||||
|
||||
struct net_device_stats stats;
|
||||
NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
|
||||
unsigned int tx_full;
|
||||
|
||||
netif_tx_interface_t *tx;
|
||||
netif_rx_interface_t *rx;
|
||||
|
||||
spinlock_t tx_lock;
|
||||
spinlock_t rx_lock;
|
||||
|
||||
unsigned int handle;
|
||||
unsigned int evtchn;
|
||||
unsigned int irq;
|
||||
|
||||
/* What is the status of our connection to the remote backend? */
|
||||
#define BEST_CLOSED 0
|
||||
#define BEST_DISCONNECTED 1
|
||||
#define BEST_CONNECTED 2
|
||||
unsigned int backend_state;
|
||||
|
||||
/* Is this interface open or closed (down or up)? */
|
||||
#define UST_CLOSED 0
|
||||
#define UST_OPEN 1
|
||||
unsigned int user_state;
|
||||
|
||||
/*
|
||||
* {tx,rx}_skbs store outstanding skbuffs. The first entry in each
|
||||
* array is an index into a chain of free entries.
|
||||
*/
|
||||
struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1];
|
||||
struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
|
||||
};
|
||||
|
||||
/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
|
||||
#define ADD_ID_TO_FREELIST(_list, _id) \
|
||||
(_list)[(_id)] = (_list)[0]; \
|
||||
(_list)[0] = (void *)(unsigned long)(_id);
|
||||
#define GET_ID_FROM_FREELIST(_list) \
|
||||
({ unsigned long _id = (unsigned long)(_list)[0]; \
|
||||
(_list)[0] = (_list)[_id]; \
|
||||
(unsigned short)_id; })
|
||||
|
||||
static struct net_device *find_dev_by_handle(unsigned int handle)
|
||||
{
|
||||
struct list_head *ent;
|
||||
struct net_private *np;
|
||||
list_for_each ( ent, &dev_list )
|
||||
{
|
||||
np = list_entry(ent, struct net_private, list);
|
||||
if ( np->handle == handle )
|
||||
return np->dev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Network interface info. */
|
||||
struct netif_ctrl {
|
||||
/** Number of interfaces. */
|
||||
int interface_n;
|
||||
/** Number of connected interfaces. */
|
||||
int connected_n;
|
||||
/** Error code. */
|
||||
int err;
|
||||
};
|
||||
|
||||
static struct netif_ctrl netctrl;
|
||||
|
||||
static void netctrl_init(void)
|
||||
{
|
||||
memset(&netctrl, 0, sizeof(netctrl));
|
||||
netctrl.interface_n = -1;
|
||||
}
|
||||
|
||||
/** Get or set a network interface error.
|
||||
*/
|
||||
static int netctrl_err(int err)
|
||||
{
|
||||
if(err < 0 && !netctrl.err){
|
||||
netctrl.err = err;
|
||||
printk(KERN_WARNING "%s> err=%d\n", __FUNCTION__, err);
|
||||
}
|
||||
return netctrl.err;
|
||||
}
|
||||
|
||||
/** Test if all network interfaces are connected.
|
||||
*
|
||||
* @return 1 if all connected, 0 if not, negative error code otherwise
|
||||
*/
|
||||
static int netctrl_connected(void)
|
||||
{
|
||||
int ok = 0;
|
||||
ok = (netctrl.err ? netctrl.err :
|
||||
(netctrl.connected_n == netctrl.interface_n));
|
||||
return ok;
|
||||
}
|
||||
|
||||
/** Count the connected network interfaces.
|
||||
*
|
||||
* @return connected count
|
||||
*/
|
||||
static int netctrl_connected_count(void)
|
||||
{
|
||||
|
||||
struct list_head *ent;
|
||||
struct net_private *np;
|
||||
unsigned int connected;
|
||||
|
||||
connected = 0;
|
||||
|
||||
list_for_each(ent, &dev_list)
|
||||
{
|
||||
np = list_entry(ent, struct net_private, list);
|
||||
if ( np->backend_state == BEST_CONNECTED )
|
||||
connected++;
|
||||
}
|
||||
|
||||
netctrl.connected_n = connected;
|
||||
return connected;
|
||||
}
|
||||
|
||||
static int network_open(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
|
||||
memset(&np->stats, 0, sizeof(np->stats));
|
||||
|
||||
np->user_state = UST_OPEN;
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
np->rx->event = np->rx_resp_cons + 1;
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void network_tx_buf_gc(struct net_device *dev)
|
||||
{
|
||||
NETIF_RING_IDX i, prod;
|
||||
unsigned short id;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if ( np->backend_state != BEST_CONNECTED )
|
||||
return;
|
||||
|
||||
do {
|
||||
prod = np->tx->resp_prod;
|
||||
|
||||
for ( i = np->tx_resp_cons; i != prod; i++ )
|
||||
{
|
||||
id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
|
||||
skb = np->tx_skbs[id];
|
||||
ADD_ID_TO_FREELIST(np->tx_skbs, id);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
np->tx_resp_cons = prod;
|
||||
|
||||
/*
|
||||
* Set a new event, then check for race with update of tx_cons. Note
|
||||
* that it is essential to schedule a callback, no matter how few
|
||||
* buffers are pending. Even if there is space in the transmit ring,
|
||||
* higher layers may be blocked because too much data is outstanding:
|
||||
* in such cases notification from Xen is likely to be the only kick
|
||||
* that we'll get.
|
||||
*/
|
||||
np->tx->event =
|
||||
prod + ((np->tx->req_prod - prod) >> 1) + 1;
|
||||
mb();
|
||||
}
|
||||
while ( prod != np->tx->resp_prod );
|
||||
|
||||
if ( np->tx_full &&
|
||||
((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE) )
|
||||
{
|
||||
np->tx_full = 0;
|
||||
if ( np->user_state == UST_OPEN )
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned short id;
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
NETIF_RING_IDX i = np->rx->req_prod;
|
||||
int nr_pfns = 0;
|
||||
|
||||
/* Make sure the batch is large enough to be worthwhile (1/2 ring). */
|
||||
if ( unlikely((i - np->rx_resp_cons) > (NETIF_RX_RING_SIZE/2)) ||
|
||||
unlikely(np->backend_state != BEST_CONNECTED) )
|
||||
return;
|
||||
|
||||
do {
|
||||
skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( unlikely(skb == NULL) )
|
||||
break;
|
||||
|
||||
skb->dev = dev;
|
||||
|
||||
if ( unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) )
|
||||
panic("alloc_skb needs to provide us page-aligned buffers.");
|
||||
|
||||
id = GET_ID_FROM_FREELIST(np->rx_skbs);
|
||||
|
||||
np->rx_skbs[id] = skb;
|
||||
|
||||
np->rx->ring[MASK_NETIF_RX_IDX(i)].req.id = id;
|
||||
|
||||
rx_pfn_array[nr_pfns] = virt_to_machine(skb->head) >> PAGE_SHIFT;
|
||||
|
||||
rx_mcl[nr_pfns].op = __HYPERVISOR_update_va_mapping;
|
||||
rx_mcl[nr_pfns].args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
|
||||
rx_mcl[nr_pfns].args[1] = 0;
|
||||
rx_mcl[nr_pfns].args[2] = 0;
|
||||
|
||||
nr_pfns++;
|
||||
}
|
||||
while ( (++i - np->rx_resp_cons) != NETIF_RX_RING_SIZE );
|
||||
|
||||
/*
|
||||
* We may have allocated buffers which have entries outstanding in the page
|
||||
* update queue -- make sure we flush those first!
|
||||
*/
|
||||
flush_page_update_queue();
|
||||
|
||||
/* After all PTEs have been zapped we blow away stale TLB entries. */
|
||||
rx_mcl[nr_pfns-1].args[2] = UVMF_FLUSH_TLB;
|
||||
|
||||
/* Give away a batch of pages. */
|
||||
rx_mcl[nr_pfns].op = __HYPERVISOR_dom_mem_op;
|
||||
rx_mcl[nr_pfns].args[0] = MEMOP_decrease_reservation;
|
||||
rx_mcl[nr_pfns].args[1] = (unsigned long)rx_pfn_array;
|
||||
rx_mcl[nr_pfns].args[2] = (unsigned long)nr_pfns;
|
||||
|
||||
/* Zap PTEs and give away pages in one big multicall. */
|
||||
(void)HYPERVISOR_multicall(rx_mcl, nr_pfns+1);
|
||||
|
||||
/* Check return status of HYPERVISOR_dom_mem_op(). */
|
||||
if ( rx_mcl[nr_pfns].args[5] != nr_pfns )
|
||||
panic("Unable to reduce memory reservation\n");
|
||||
|
||||
np->rx->req_prod = i;
|
||||
}
|
||||
|
||||
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
unsigned short id;
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
netif_tx_request_t *tx;
|
||||
NETIF_RING_IDX i;
|
||||
|
||||
if ( unlikely(np->tx_full) )
|
||||
{
|
||||
printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name);
|
||||
netif_stop_queue(dev);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if ( unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
|
||||
PAGE_SIZE) )
|
||||
{
|
||||
struct sk_buff *new_skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( unlikely(new_skb == NULL) )
|
||||
return 1;
|
||||
skb_put(new_skb, skb->len);
|
||||
memcpy(new_skb->data, skb->data, skb->len);
|
||||
dev_kfree_skb(skb);
|
||||
skb = new_skb;
|
||||
}
|
||||
|
||||
spin_lock_irq(&np->tx_lock);
|
||||
|
||||
if ( np->backend_state != BEST_CONNECTED )
|
||||
{
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
i = np->tx->req_prod;
|
||||
|
||||
id = GET_ID_FROM_FREELIST(np->tx_skbs);
|
||||
np->tx_skbs[id] = skb;
|
||||
|
||||
tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
|
||||
|
||||
tx->id = id;
|
||||
tx->addr = virt_to_machine(skb->data);
|
||||
tx->size = skb->len;
|
||||
|
||||
wmb();
|
||||
np->tx->req_prod = i + 1;
|
||||
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
if ( (i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1) )
|
||||
{
|
||||
np->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
|
||||
np->stats.tx_bytes += skb->len;
|
||||
np->stats.tx_packets++;
|
||||
|
||||
/* Only notify Xen if there are no outstanding responses. */
|
||||
mb();
|
||||
if ( np->tx->resp_prod == i )
|
||||
notify_via_evtchn(np->evtchn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
struct net_private *np = dev->priv;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&np->tx_lock, flags);
|
||||
network_tx_buf_gc(dev);
|
||||
spin_unlock_irqrestore(&np->tx_lock, flags);
|
||||
|
||||
if ( (np->rx_resp_cons != np->rx->resp_prod) &&
|
||||
(np->user_state == UST_OPEN) )
|
||||
netif_rx_schedule(dev);
|
||||
}
|
||||
|
||||
|
||||
static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
netif_rx_response_t *rx;
|
||||
NETIF_RING_IDX i;
|
||||
mmu_update_t *mmu = rx_mmu;
|
||||
multicall_entry_t *mcl = rx_mcl;
|
||||
int work_done, budget, more_to_do = 1;
|
||||
struct sk_buff_head rxq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
|
||||
if ( np->backend_state != BEST_CONNECTED )
|
||||
{
|
||||
spin_unlock(&np->rx_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
if ( (budget = *pbudget) > dev->quota )
|
||||
budget = dev->quota;
|
||||
|
||||
for ( i = np->rx_resp_cons, work_done = 0;
|
||||
(i != np->rx->resp_prod) && (work_done < budget);
|
||||
i++, work_done++ )
|
||||
{
|
||||
rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
|
||||
|
||||
skb = np->rx_skbs[rx->id];
|
||||
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
|
||||
|
||||
if ( unlikely(rx->status <= 0) )
|
||||
{
|
||||
/* Gate this error. We get a (valid) slew of them on suspend. */
|
||||
if ( np->user_state != UST_OPEN )
|
||||
printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK);
|
||||
skb_put(skb, rx->status);
|
||||
|
||||
np->stats.rx_packets++;
|
||||
np->stats.rx_bytes += rx->status;
|
||||
|
||||
/* Remap the page. */
|
||||
mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
|
||||
mmu++;
|
||||
mcl->op = __HYPERVISOR_update_va_mapping;
|
||||
mcl->args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
|
||||
mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL;
|
||||
mcl->args[2] = 0;
|
||||
mcl++;
|
||||
|
||||
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] =
|
||||
rx->addr >> PAGE_SHIFT;
|
||||
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
}
|
||||
|
||||
/* Do all the remapping work, and M->P updates, in one big hypercall. */
|
||||
if ( likely((mcl - rx_mcl) != 0) )
|
||||
{
|
||||
mcl->op = __HYPERVISOR_mmu_update;
|
||||
mcl->args[0] = (unsigned long)rx_mmu;
|
||||
mcl->args[1] = mmu - rx_mmu;
|
||||
mcl->args[2] = 0;
|
||||
mcl++;
|
||||
(void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
}
|
||||
|
||||
while ( (skb = __skb_dequeue(&rxq)) != NULL )
|
||||
{
|
||||
/* Set the shared-info area, which is hidden behind the real data. */
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
/* Ethernet-specific work. Delayed to here as it peeks the header. */
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
|
||||
/* Pass it up. */
|
||||
netif_rx(skb);
|
||||
dev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
np->rx_resp_cons = i;
|
||||
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
*pbudget -= work_done;
|
||||
dev->quota -= work_done;
|
||||
|
||||
if ( work_done < budget )
|
||||
{
|
||||
local_irq_save(flags);
|
||||
|
||||
np->rx->event = i + 1;
|
||||
|
||||
/* Deal with hypervisor racing our resetting of rx_event. */
|
||||
mb();
|
||||
if ( np->rx->resp_prod == i )
|
||||
{
|
||||
__netif_rx_complete(dev);
|
||||
more_to_do = 0;
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
spin_unlock(&np->rx_lock);
|
||||
|
||||
return more_to_do;
|
||||
}
|
||||
|
||||
|
||||
static int network_close(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = dev->priv;
|
||||
np->user_state = UST_CLOSED;
|
||||
netif_stop_queue(np->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct net_device_stats *network_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct net_private *np = (struct net_private *)dev->priv;
|
||||
return &np->stats;
|
||||
}
|
||||
|
||||
|
||||
static void network_connect(struct net_device *dev,
|
||||
netif_fe_interface_status_changed_t *status)
|
||||
{
|
||||
struct net_private *np;
|
||||
int i, requeue_idx;
|
||||
netif_tx_request_t *tx;
|
||||
|
||||
np = dev->priv;
|
||||
spin_lock_irq(&np->rx_lock);
|
||||
spin_lock(&np->tx_lock);
|
||||
|
||||
/* Recovery procedure: */
|
||||
|
||||
/* Step 1: Reinitialise variables. */
|
||||
np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
|
||||
np->rx->event = 1;
|
||||
|
||||
/* Step 2: Rebuild the RX and TX ring contents.
|
||||
* NB. We could just free the queued TX packets now but we hope
|
||||
* that sending them out might do some good. We have to rebuild
|
||||
* the RX ring because some of our pages are currently flipped out
|
||||
* so we can't just free the RX skbs.
|
||||
* NB2. Freelist index entries are always going to be less than
|
||||
* __PAGE_OFFSET, whereas pointers to skbs will always be equal or
|
||||
* greater than __PAGE_OFFSET: we use this property to distinguish
|
||||
* them.
|
||||
*/
|
||||
|
||||
/* Rebuild the TX buffer freelist and the TX ring itself.
|
||||
* NB. This reorders packets. We could keep more private state
|
||||
* to avoid this but maybe it doesn't matter so much given the
|
||||
* interface has been down.
|
||||
*/
|
||||
for ( requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++ )
|
||||
{
|
||||
if ( (unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET )
|
||||
{
|
||||
struct sk_buff *skb = np->tx_skbs[i];
|
||||
|
||||
tx = &np->tx->ring[requeue_idx++].req;
|
||||
|
||||
tx->id = i;
|
||||
tx->addr = virt_to_machine(skb->data);
|
||||
tx->size = skb->len;
|
||||
|
||||
np->stats.tx_bytes += skb->len;
|
||||
np->stats.tx_packets++;
|
||||
}
|
||||
}
|
||||
wmb();
|
||||
np->tx->req_prod = requeue_idx;
|
||||
|
||||
/* Rebuild the RX buffer freelist and the RX ring itself. */
|
||||
for ( requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++ )
|
||||
if ( (unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET )
|
||||
np->rx->ring[requeue_idx++].req.id = i;
|
||||
wmb();
|
||||
np->rx->req_prod = requeue_idx;
|
||||
|
||||
/* Step 3: All public and private state should now be sane. Get
|
||||
* ready to start sending and receiving packets and give the driver
|
||||
* domain a kick because we've probably just requeued some
|
||||
* packets.
|
||||
*/
|
||||
np->backend_state = BEST_CONNECTED;
|
||||
notify_via_evtchn(status->evtchn);
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
if ( np->user_state == UST_OPEN )
|
||||
netif_start_queue(dev);
|
||||
|
||||
spin_unlock(&np->tx_lock);
|
||||
spin_unlock_irq(&np->rx_lock);
|
||||
}
|
||||
|
||||
static void netif_status_change(netif_fe_interface_status_changed_t *status)
|
||||
{
|
||||
ctrl_msg_t cmsg;
|
||||
netif_fe_interface_connect_t up;
|
||||
struct net_device *dev;
|
||||
struct net_private *np;
|
||||
|
||||
if ( netctrl.interface_n <= 0 )
|
||||
{
|
||||
printk(KERN_WARNING "Status change: no interfaces\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev = find_dev_by_handle(status->handle);
|
||||
if(!dev){
|
||||
printk(KERN_WARNING "Status change: invalid netif handle %u\n",
|
||||
status->handle);
|
||||
return;
|
||||
}
|
||||
np = dev->priv;
|
||||
|
||||
switch ( status->status )
|
||||
{
|
||||
case NETIF_INTERFACE_STATUS_DESTROYED:
|
||||
printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n",
|
||||
np->backend_state);
|
||||
break;
|
||||
|
||||
case NETIF_INTERFACE_STATUS_DISCONNECTED:
|
||||
if ( np->backend_state != BEST_CLOSED )
|
||||
{
|
||||
printk(KERN_WARNING "Unexpected netif-DISCONNECTED message"
|
||||
" in state %d\n", np->backend_state);
|
||||
printk(KERN_INFO "Attempting to reconnect network interface\n");
|
||||
|
||||
/* Begin interface recovery.
|
||||
*
|
||||
* NB. Whilst we're recovering, we turn the carrier state off. We
|
||||
* take measures to ensure that this device isn't used for
|
||||
* anything. We also stop the queue for this device. Various
|
||||
* different approaches (e.g. continuing to buffer packets) have
|
||||
* been tested but don't appear to improve the overall impact on
|
||||
* TCP connections.
|
||||
*
|
||||
* TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
|
||||
* is initiated by a special "RESET" message - disconnect could
|
||||
* just mean we're not allowed to use this interface any more.
|
||||
*/
|
||||
|
||||
/* 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(dev);
|
||||
np->backend_state = BEST_DISCONNECTED;
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
|
||||
/* Free resources. */
|
||||
free_irq(np->irq, dev);
|
||||
unbind_evtchn_from_irq(np->evtchn);
|
||||
free_page((unsigned long)np->tx);
|
||||
free_page((unsigned long)np->rx);
|
||||
}
|
||||
|
||||
/* Move from CLOSED to DISCONNECTED state. */
|
||||
np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
|
||||
np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
|
||||
memset(np->tx, 0, PAGE_SIZE);
|
||||
memset(np->rx, 0, PAGE_SIZE);
|
||||
np->backend_state = BEST_DISCONNECTED;
|
||||
|
||||
/* Construct an interface-CONNECT message for the domain controller. */
|
||||
cmsg.type = CMSG_NETIF_FE;
|
||||
cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT;
|
||||
cmsg.length = sizeof(netif_fe_interface_connect_t);
|
||||
up.handle = status->handle;
|
||||
up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
|
||||
up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
|
||||
memcpy(cmsg.msg, &up, sizeof(up));
|
||||
|
||||
/* Tell the controller to bring up the interface. */
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
break;
|
||||
|
||||
case NETIF_INTERFACE_STATUS_CONNECTED:
|
||||
if ( np->backend_state == BEST_CLOSED )
|
||||
{
|
||||
printk(KERN_WARNING "Unexpected netif-CONNECTED message"
|
||||
" in state %d\n", np->backend_state);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(dev->dev_addr, status->mac, ETH_ALEN);
|
||||
|
||||
network_connect(dev, status);
|
||||
|
||||
np->evtchn = status->evtchn;
|
||||
np->irq = bind_evtchn_to_irq(np->evtchn);
|
||||
(void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM,
|
||||
dev->name, dev);
|
||||
|
||||
netctrl_connected_count();
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "Status change to unknown value %d\n",
|
||||
status->status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a network device.
|
||||
* @param handle device handle
|
||||
* @param val return parameter for created device
|
||||
* @return 0 on success, error code otherwise
|
||||
*/
|
||||
static int create_netdev(int handle, struct net_device **val)
|
||||
{
|
||||
int i, err = 0;
|
||||
struct net_device *dev = NULL;
|
||||
struct net_private *np = NULL;
|
||||
|
||||
if ( (dev = alloc_etherdev(sizeof(struct net_private))) == NULL )
|
||||
{
|
||||
printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__);
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
np = dev->priv;
|
||||
np->backend_state = BEST_CLOSED;
|
||||
np->user_state = UST_CLOSED;
|
||||
np->handle = handle;
|
||||
|
||||
spin_lock_init(&np->tx_lock);
|
||||
spin_lock_init(&np->rx_lock);
|
||||
|
||||
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
|
||||
for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ )
|
||||
np->tx_skbs[i] = (void *)(i+1);
|
||||
for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ )
|
||||
np->rx_skbs[i] = (void *)(i+1);
|
||||
|
||||
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;
|
||||
|
||||
if ( (err = register_netdev(dev)) != 0 )
|
||||
{
|
||||
printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
|
||||
goto exit;
|
||||
}
|
||||
np->dev = dev;
|
||||
list_add(&np->list, &dev_list);
|
||||
|
||||
exit:
|
||||
if ( (err != 0) && (dev != NULL ) )
|
||||
kfree(dev);
|
||||
else if ( val != NULL )
|
||||
*val = dev;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the network control interface. Set the number of network devices
|
||||
* and create them.
|
||||
*/
|
||||
static void netif_driver_status_change(
|
||||
netif_fe_driver_status_changed_t *status)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
netctrl.interface_n = status->nr_interfaces;
|
||||
netctrl.connected_n = 0;
|
||||
|
||||
for ( i = 0; i < netctrl.interface_n; i++ )
|
||||
{
|
||||
if ( (err = create_netdev(i, NULL)) != 0 )
|
||||
{
|
||||
netctrl_err(err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
|
||||
{
|
||||
int respond = 1;
|
||||
|
||||
switch ( msg->subtype )
|
||||
{
|
||||
case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
|
||||
if ( msg->length != sizeof(netif_fe_interface_status_changed_t) )
|
||||
goto error;
|
||||
netif_status_change((netif_fe_interface_status_changed_t *)
|
||||
&msg->msg[0]);
|
||||
break;
|
||||
|
||||
case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
|
||||
if ( msg->length != sizeof(netif_fe_driver_status_changed_t) )
|
||||
goto error;
|
||||
netif_driver_status_change((netif_fe_driver_status_changed_t *)
|
||||
&msg->msg[0]);
|
||||
/* Message is a response */
|
||||
respond = 0;
|
||||
break;
|
||||
|
||||
error:
|
||||
default:
|
||||
msg->length = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( respond )
|
||||
ctrl_if_send_response(msg);
|
||||
}
|
||||
|
||||
|
||||
static int __init netif_init(void)
|
||||
{
|
||||
ctrl_msg_t cmsg;
|
||||
netif_fe_driver_status_changed_t st;
|
||||
int err = 0, wait_i, wait_n = 20;
|
||||
|
||||
if ( (start_info.flags & SIF_INITDOMAIN) ||
|
||||
(start_info.flags & SIF_NET_BE_DOMAIN) )
|
||||
return 0;
|
||||
|
||||
printk("Initialising Xen virtual ethernet frontend driver");
|
||||
|
||||
INIT_LIST_HEAD(&dev_list);
|
||||
|
||||
netctrl_init();
|
||||
|
||||
(void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
|
||||
CALLBACK_IN_BLOCKING_CONTEXT);
|
||||
|
||||
/* Send a driver-UP notification to the domain controller. */
|
||||
cmsg.type = CMSG_NETIF_FE;
|
||||
cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
|
||||
cmsg.length = sizeof(netif_fe_driver_status_changed_t);
|
||||
st.status = NETIF_DRIVER_STATUS_UP;
|
||||
st.nr_interfaces = 0;
|
||||
memcpy(cmsg.msg, &st, sizeof(st));
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
/* Wait for all interfaces to be connected. */
|
||||
for ( wait_i = 0; ; wait_i++)
|
||||
{
|
||||
if ( (err = (wait_i < wait_n) ? netctrl_connected() : -ENETDOWN) != 0 )
|
||||
{
|
||||
err = (err > 0) ? 0 : err;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(1);
|
||||
}
|
||||
|
||||
if ( err )
|
||||
ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
__initcall(netif_init);
|
||||
@@ -225,5 +225,5 @@ ln -sf ../../i386/mm/extable.c
|
||||
ln -sf ../../i386/mm/pageattr.c
|
||||
cd ../drivers/console
|
||||
ln -sf ../../../../${LINUX_26}/drivers/xen/console/console.c
|
||||
#cd ../netif/frontend
|
||||
#ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c
|
||||
cd ../netif/frontend
|
||||
ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c
|
||||
@@ -16,6 +16,10 @@ config ARCH_XEN
|
||||
default y
|
||||
|
||||
|
||||
config NO_IDLE_HZ
|
||||
bool
|
||||
default y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
#config VT
|
||||
|
||||
@@ -87,6 +87,17 @@ EXPORT_SYMBOL(i8253_lock);
|
||||
|
||||
struct timer_opts *cur_timer = &timer_none;
|
||||
|
||||
/* These are peridically updated in shared_info, and then copied here. */
|
||||
static u32 shadow_tsc_stamp;
|
||||
static u64 shadow_system_time;
|
||||
static u32 shadow_time_version;
|
||||
static struct timeval shadow_tv;
|
||||
|
||||
/* Keep track of last time we did processing/updating of jiffies and xtime. */
|
||||
static u64 processed_system_time; /* System time (ns) at last processing. */
|
||||
|
||||
#define NS_PER_TICK (1000000000ULL/HZ)
|
||||
|
||||
/*
|
||||
* This version of gettimeofday has microsecond resolution
|
||||
* and better than microsecond precision on fast x86 machines with TSC.
|
||||
@@ -203,6 +214,24 @@ unsigned long long monotonic_clock(void)
|
||||
EXPORT_SYMBOL(monotonic_clock);
|
||||
|
||||
|
||||
/*
|
||||
* Reads a consistent set of time-base values from Xen, into a shadow data
|
||||
* area. Must be called with the xtime_lock held for writing.
|
||||
*/
|
||||
static void __get_time_values_from_xen(void)
|
||||
{
|
||||
do {
|
||||
shadow_time_version = HYPERVISOR_shared_info->time_version2;
|
||||
rmb();
|
||||
shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec;
|
||||
shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec;
|
||||
shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp.tsc_bits;
|
||||
shadow_system_time = HYPERVISOR_shared_info->system_time;
|
||||
rmb();
|
||||
}
|
||||
while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* as well as call the "do_timer()" routine every clocktick
|
||||
@@ -210,6 +239,9 @@ EXPORT_SYMBOL(monotonic_clock);
|
||||
static inline void do_timer_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
s64 delta;
|
||||
unsigned long ticks = 0;
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
if (timer_ack) {
|
||||
/*
|
||||
@@ -226,7 +258,23 @@ static inline void do_timer_interrupt(int irq, void *dev_id,
|
||||
}
|
||||
#endif
|
||||
|
||||
do_timer_interrupt_hook(regs);
|
||||
__get_time_values_from_xen();
|
||||
|
||||
delta = (s64)(shadow_system_time - processed_system_time);
|
||||
if (delta < 0) {
|
||||
printk("Timer ISR: Time went backwards: %lld\n", delta);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process elapsed jiffies since last call. */
|
||||
while (delta >= NS_PER_TICK) {
|
||||
ticks++;
|
||||
delta -= NS_PER_TICK;
|
||||
processed_system_time += NS_PER_TICK;
|
||||
|
||||
if (regs)
|
||||
do_timer_interrupt_hook(regs);
|
||||
}
|
||||
|
||||
#if 0 /* XEN PRIV */
|
||||
/*
|
||||
@@ -288,8 +336,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
|
||||
cur_timer->mark_offset();
|
||||
|
||||
if (regs) /* XXXcl check regs in do_timer_interrupt */
|
||||
do_timer_interrupt(irq, NULL, regs);
|
||||
do_timer_interrupt(irq, NULL, regs);
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
return IRQ_HANDLED;
|
||||
@@ -410,3 +457,45 @@ void __init time_init(void)
|
||||
|
||||
(void)setup_irq(time_irq, &irq_timer);
|
||||
}
|
||||
|
||||
/* Convert jiffies to system time. Call with xtime_lock held for reading. */
|
||||
static inline u64 __jiffies_to_st(unsigned long j)
|
||||
{
|
||||
return processed_system_time + ((j - jiffies) * NS_PER_TICK);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function works out when the the next timer function has to be
|
||||
* executed (by looking at the timer list) and sets the Xen one-shot
|
||||
* domain timer to the appropriate value. This is typically called in
|
||||
* cpu_idle() before the domain blocks.
|
||||
*
|
||||
* The function returns a non-0 value on error conditions.
|
||||
*
|
||||
* It must be called with interrupts disabled.
|
||||
*/
|
||||
extern spinlock_t timerlist_lock;
|
||||
int set_timeout_timer(void)
|
||||
{
|
||||
u64 alarm = 0;
|
||||
int ret = 0;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
spin_lock(&timerlist_lock);
|
||||
|
||||
/*
|
||||
* This is safe against long blocking (since calculations are not based on
|
||||
* TSC deltas). It is also safe against warped system time since
|
||||
* suspend-resume is cooperative and we would first get locked out. It is
|
||||
* safe against normal updates of jiffies since interrupts are off.
|
||||
*/
|
||||
alarm = __jiffies_to_st(next_timer_interrupt());
|
||||
|
||||
/* Failure is pretty bad, but we'd best soldier on. */
|
||||
if ( HYPERVISOR_set_timer_op(alarm) != 0 )
|
||||
ret = -1;
|
||||
|
||||
spin_unlock(&timerlist_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -10,11 +10,16 @@
|
||||
|
||||
void xen_cpu_idle (void)
|
||||
{
|
||||
// local_irq_disable();
|
||||
if (need_resched()) {
|
||||
// local_irq_enable();
|
||||
local_irq_disable();
|
||||
if (need_resched() || !list_empty(&RCU_curlist(cpu)))
|
||||
local_irq_enable();
|
||||
return;
|
||||
}
|
||||
// local_irq_enable();
|
||||
if (set_timeout_timer() == 0) {
|
||||
/* NB. Blocking reenable events in a race-free manner. */
|
||||
HYPERVISOR_block();
|
||||
return;
|
||||
}
|
||||
local_irq_enable();
|
||||
HYPERVISOR_yield();
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
/******************************************************************************
|
||||
* network.c
|
||||
*
|
||||
* Virtual network driver for conversing with remote driver backends.
|
||||
*
|
||||
* Copyright (c) 2002-2004, K A Fraser
|
||||
@@ -8,13 +6,12 @@
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
@@ -30,7 +27,13 @@
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
#include <asm-xen/netif.h>
|
||||
#else
|
||||
#include "../netif.h"
|
||||
#define irqreturn_t void
|
||||
#define IRQ_HANDLED
|
||||
#endif
|
||||
|
||||
#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
|
||||
|
||||
@@ -368,7 +371,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
struct net_private *np = dev->priv;
|
||||
@@ -381,8 +384,6 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
if ( (np->rx_resp_cons != np->rx->resp_prod) &&
|
||||
(np->user_state == UST_OPEN) )
|
||||
netif_rx_schedule(dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
@@ -417,18 +418,25 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
{
|
||||
rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
|
||||
|
||||
skb = np->rx_skbs[rx->id];
|
||||
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
|
||||
|
||||
/*
|
||||
* An error here is very odd. Usually indicates a backend bug,
|
||||
* low-memory condition, or that we didn't have reservation headroom.
|
||||
* Whatever - print an error and queue the id again straight away.
|
||||
*/
|
||||
if ( unlikely(rx->status <= 0) )
|
||||
{
|
||||
/* Gate this error. We get a (valid) slew of them on suspend. */
|
||||
if ( np->user_state != UST_OPEN )
|
||||
if ( np->user_state == UST_OPEN )
|
||||
printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
|
||||
dev_kfree_skb(skb);
|
||||
np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
|
||||
wmb();
|
||||
np->rx->req_prod++;
|
||||
continue;
|
||||
}
|
||||
|
||||
skb = np->rx_skbs[rx->id];
|
||||
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
|
||||
|
||||
skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK);
|
||||
skb_put(skb, rx->status);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ setup(name = 'xen',
|
||||
'xen.util',
|
||||
'xen.xend',
|
||||
'xen.xend.server',
|
||||
'xen.xend.sv',
|
||||
'xen.xm',
|
||||
],
|
||||
ext_package = "xen.lowlevel",
|
||||
|
||||
@@ -100,7 +100,7 @@ def lookup_raw_partn(name):
|
||||
if line:
|
||||
return [ { 'device' : blkdev_name_to_number(p),
|
||||
'start_sector' : long(0),
|
||||
'nr_sectors' : long(line) * 2,
|
||||
'nr_sectors' : long(1L<<63),
|
||||
'type' : 'Disk' } ]
|
||||
else:
|
||||
# see if this is a hex device number
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
# todo Support security settings etc. in the config file.
|
||||
# todo Support command-line args.
|
||||
|
||||
from twisted.web import server
|
||||
from twisted.web import resource
|
||||
from twisted.web import server, static
|
||||
from twisted.web import resource, script
|
||||
from twisted.internet import reactor
|
||||
|
||||
from xen.xend import XendRoot
|
||||
@@ -44,8 +44,12 @@ def create(port=None, interface=None, bridge=0):
|
||||
if bridge or xroot.rebooted:
|
||||
Vifctl.network('start')
|
||||
root = resource.Resource()
|
||||
sv = static.File( "/usr/lib/python2.2/site-packages/xen/xend/sv/" )
|
||||
sv.indexNames=['Main.rpy']
|
||||
sv.processors={'.rpy':script.ResourceScript}
|
||||
xend = SrvRoot()
|
||||
root.putChild('xend', xend)
|
||||
root.putChild('sv', sv)
|
||||
site = server.Site(root)
|
||||
reactor.listenTCP(port, site, interface=interface)
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
from HTMLBase import HTMLBase
|
||||
from XendClientDeferred import server
|
||||
from xen.xend import PrettyPrint
|
||||
|
||||
from xen.xend.sv.util import *
|
||||
from xen.xend.sv.GenTabbed import *
|
||||
|
||||
class DomInfo( GenTabbed ):
|
||||
|
||||
def __init__( self, urlWriter, callback ):
|
||||
|
||||
self.dom = 0;
|
||||
|
||||
def tabUrlWriter( tab ):
|
||||
return urlWriter( "mod=info&dom=%s%s" % ( self.dom, tab ) )
|
||||
|
||||
GenTabbed.__init__( self, tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGenTab, DomSXPTab, NullTab ], callback )
|
||||
|
||||
def write_BODY( self, request ):
|
||||
dom = request.args.get('dom')
|
||||
|
||||
if dom is None or len(dom) != 1:
|
||||
request.write( "<p>Please Select a Domain</p>" )
|
||||
return None
|
||||
else:
|
||||
self.dom = dom[0]
|
||||
|
||||
GenTabbed.write_BODY( self, request )
|
||||
|
||||
class DomGenTab( GeneralTab ):
|
||||
|
||||
def __init__( self ):
|
||||
|
||||
titles = {}
|
||||
|
||||
titles[ 'ID' ] = 'dom'
|
||||
titles[ 'Name' ] = 'name'
|
||||
titles[ 'CPU' ] = 'cpu'
|
||||
titles[ 'Memory' ] = ( 'mem', memoryFormatter )
|
||||
titles[ 'State' ] = ( 'state', stateFormatter )
|
||||
titles[ 'Total CPU' ] = ( 'cpu_time', smallTimeFormatter )
|
||||
titles[ 'Up Time' ] = ( 'up_time', bigTimeFormatter )
|
||||
|
||||
GeneralTab.__init__( self, "General Domain Info", {}, titles )
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
dom = request.args.get('dom')
|
||||
|
||||
if dom is None or len(dom) != 1:
|
||||
request.write( "<p>Please Select a Domain</p>" )
|
||||
return None
|
||||
else:
|
||||
self.dom = dom[0]
|
||||
|
||||
deferred = getDomInfoHash( self.dom )
|
||||
deferred.addCallback( self.continue_BODY, request, callback )
|
||||
|
||||
def continue_BODY( self, dict, request, callback ):
|
||||
|
||||
self.dict = dict
|
||||
|
||||
GeneralTab.write_BODY( self, request, callback )
|
||||
|
||||
class DomSXPTab( PreTab ):
|
||||
|
||||
def __init__( self ):
|
||||
self.dom = 0
|
||||
PreTab.__init__( self, "" )
|
||||
|
||||
def fn( self, x, request ):
|
||||
class tmp:
|
||||
def __init__( self ):
|
||||
self.str = ""
|
||||
def write( self, str ):
|
||||
self.str = self.str + str
|
||||
temp = tmp()
|
||||
PrettyPrint.prettyprint( x, out=temp )
|
||||
self.source = temp.str
|
||||
return request
|
||||
|
||||
def fn2( self, request, callback ):
|
||||
PreTab.write_BODY( self, request, callback )
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
dom = request.args.get('dom')
|
||||
|
||||
if dom is None or len(dom) != 1:
|
||||
request.write( "<p>Please Select a Domain</p>" )
|
||||
return None
|
||||
else:
|
||||
self.dom = dom[0]
|
||||
|
||||
deferred = server.xend_domain( self.dom )
|
||||
|
||||
deferred.addCallback( self.fn, request )
|
||||
deferred.addCallback( self.fn2, callback )
|
||||
def errback( x ):
|
||||
print ">err ", x
|
||||
deferred.addErrback( errback )
|
||||
@@ -0,0 +1,101 @@
|
||||
from twisted.web import resource
|
||||
from twisted.web.server import NOT_DONE_YET
|
||||
|
||||
from XendClientDeferred import server as XendServer
|
||||
from xen.xend import sxp
|
||||
|
||||
from xen.xend.sv.HTMLBase import HTMLBase
|
||||
from xen.xend.sv.util import *
|
||||
|
||||
from twisted.internet import reactor
|
||||
|
||||
class DomList( HTMLBase ):
|
||||
|
||||
isLeaf = True
|
||||
|
||||
def __init__( self, urlWriter, callback ):
|
||||
HTMLBase.__init__(self)
|
||||
self.urlWriter = urlWriter
|
||||
self.head = None
|
||||
self.long = None
|
||||
self.rendered_domains = {}
|
||||
self.domCount = 0
|
||||
self.callback = callback
|
||||
|
||||
def write_BODY( self, request, head=True, long=True ):
|
||||
deferred = XendServer.xend_domains()
|
||||
deferred.addCallback( self.get_domain_info, request )
|
||||
deferred.addErrback( self.errback )
|
||||
|
||||
self.head = head
|
||||
self.long = long
|
||||
|
||||
def errback( self, err ):
|
||||
print 'errback>', err
|
||||
|
||||
def get_domain_info( self, domains, request ):
|
||||
|
||||
self.domCount = len( domains )
|
||||
|
||||
for domain in domains:
|
||||
deferred = getDomInfoHash( domain )
|
||||
deferred.addCallback( self.render_domain, request )
|
||||
deferred.addErrback( self.errback )
|
||||
|
||||
def render_domain( self, domInfoHash, request ):
|
||||
|
||||
domStr = "<td class='domainInfo' align='center'>%(dom)-4d</td>\n" % domInfoHash
|
||||
|
||||
url = self.urlWriter( "mod=info&dom=%(dom)-4d" % domInfoHash )
|
||||
|
||||
domStr += "<td class='domainInfo' align='center'><a href='%s'>%s</a></td>\n" % ( url, domInfoHash['name'] )
|
||||
|
||||
if self.long:
|
||||
domStr += "<td class='domainInfo' align='center'>%(mem)7d</td>\n" % domInfoHash
|
||||
domStr += "<td class='domainInfo' align='center'>%(cpu)3d</td>\n" % domInfoHash
|
||||
|
||||
domStr += "<td class='domainInfo' align='center'>%(state)5s</td>\n" % domInfoHash
|
||||
|
||||
if self.long:
|
||||
domStr += "<td class='domainInfo' align='center'>%(cpu_time)7.1f</td>\n" % domInfoHash
|
||||
|
||||
self.rendered_domains[ domInfoHash[ 'dom' ] ] = domStr
|
||||
self.domCount -= 1
|
||||
|
||||
if self.domCount == 0:
|
||||
self.finish_write_BODY( request )
|
||||
|
||||
def finish_write_BODY( self, request ):
|
||||
|
||||
request.write( "\n<table style='border:0px solid white' cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
|
||||
|
||||
if self.head:
|
||||
request.write( "<tr class='domainInfoHead'>" )
|
||||
self.write_DOMAIN_HEAD( request, self.long )
|
||||
request.write( "</tr>" )
|
||||
|
||||
odd = True
|
||||
for domain in self.rendered_domains.values():
|
||||
if odd:
|
||||
request.write( "<tr class='domainInfoOdd'>\n" )
|
||||
odd = False
|
||||
else:
|
||||
request.write( "<tr class='domainInfoEven'>\n" )
|
||||
odd = True
|
||||
request.write( domain )
|
||||
request.write( "</tr>\n" )
|
||||
|
||||
request.write( "</table>\n" )
|
||||
|
||||
self.callback( request )
|
||||
|
||||
def write_DOMAIN_HEAD( self, request, long=True ):
|
||||
request.write( "<td class='domainInfoHead' align='center'>Domain</td>\n" )
|
||||
request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )
|
||||
if long:
|
||||
request.write( "<td class='domainInfoHead' align='center'>Memory / Mb</td>\n" )
|
||||
request.write( "<td class='domainInfoHead' align='center'>CPU</td>\n" )
|
||||
request.write( "<td class='domainInfoHead' align='center'>State</td>\n" )
|
||||
if long:
|
||||
request.write( "<td class='domainInfoHead' align='center'>CPU time / s</td>\n" )
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import types
|
||||
|
||||
from HTMLBase import HTMLBase
|
||||
from TabView import TabView
|
||||
|
||||
class GenTabbed( HTMLBase ):
|
||||
|
||||
def __init__( self, urlWriter, tabStrings, tabObjects, callback ):
|
||||
HTMLBase.__init__(self)
|
||||
self.tab = 0;
|
||||
self.tabStrings = tabStrings
|
||||
self.tabObjects = tabObjects
|
||||
self.urlWriter = urlWriter
|
||||
self.callback = callback
|
||||
|
||||
def write_BODY( self, request, urlWriter = None ):
|
||||
tab = request.args.get('tab')
|
||||
|
||||
if tab is None or len( tab) != 1:
|
||||
self.tab = 0
|
||||
else:
|
||||
self.tab = int( tab[0] )
|
||||
|
||||
request.write( "<table style='' width='100%' border='0' cellspacing='0' cellpadding='0'>" )
|
||||
request.write( "<tr><td>" )
|
||||
|
||||
TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request )
|
||||
|
||||
request.write( "</td></tr><tr><td>" )
|
||||
|
||||
render_tab = self.tabObjects[ self.tab ]()
|
||||
|
||||
if render_tab is None:
|
||||
request.write( "<p>Bad Tab</p>" )
|
||||
self.finish_BODY( request )
|
||||
else:
|
||||
render_tab.write_BODY( request, self.finish_BODY )
|
||||
|
||||
def finish_BODY( self, request ):
|
||||
|
||||
request.write( "</td></tr></table>" )
|
||||
|
||||
self.callback( request )
|
||||
|
||||
class PreTab( HTMLBase ):
|
||||
|
||||
def __init__( self, source ):
|
||||
HTMLBase.__init__( self )
|
||||
self.source = source
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
|
||||
request.write( "<div style='display: block; overflow: auto; border: 0px solid black; height: 400px; width: 540px; padding: 5px; z-index:0; align: center'><pre>" )
|
||||
|
||||
request.write( self.source )
|
||||
|
||||
request.write( "</pre></div>" )
|
||||
|
||||
callback( request )
|
||||
|
||||
class GeneralTab( HTMLBase ):
|
||||
|
||||
def __init__( self, title, dict, titles ):
|
||||
HTMLBase.__init__( self )
|
||||
self.title = title
|
||||
self.dict = dict
|
||||
self.titles = titles
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
|
||||
request.write( "<p><u>%s</u></p>" % self.title )
|
||||
|
||||
request.write( "<table width='100%' cellspacing='0' cellpadding='0' border='0'>" )
|
||||
|
||||
def writeAttr( niceName, attr, formatter=None ):
|
||||
if type( attr ) is types.TupleType:
|
||||
( attr, formatter ) = attr
|
||||
|
||||
if attr in self.dict:
|
||||
if formatter:
|
||||
temp = formatter( self.dict[ attr ] )
|
||||
else:
|
||||
temp = str( self.dict[ attr ] )
|
||||
request.write( "<tr><td width='50%%'><p>%s:</p></td><td width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
|
||||
|
||||
for niceName, attr in self.titles.items():
|
||||
writeAttr( niceName, attr )
|
||||
|
||||
request.write( "</table>" )
|
||||
|
||||
callback( request )
|
||||
|
||||
class NullTab( HTMLBase ):
|
||||
|
||||
def __init__( self ):
|
||||
HTMLBase.__init__( self )
|
||||
self.title = "Null Tab"
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
request.write( "<p>%s</p>" % self.title )
|
||||
callback( request )
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from twisted.web import server, resource
|
||||
from twisted.internet import reactor
|
||||
|
||||
class HTMLBase( resource.Resource ):
|
||||
|
||||
isLeaf = True
|
||||
|
||||
def __init__( self ):
|
||||
resource.Resource.__init__(self)
|
||||
|
||||
def render_GET( self, request ):
|
||||
self.write_TOP( request )
|
||||
return self.write_BODY( request, self.finish_render_GET )
|
||||
|
||||
def finish_render_GET( self, request ):
|
||||
self.write_BOTTOM( request )
|
||||
request.finish()
|
||||
|
||||
def write_BODY( self, request ):
|
||||
request.write( "BODY" )
|
||||
|
||||
def write_TOP( self, request ):
|
||||
request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
|
||||
request.write( '</head><body>' )
|
||||
|
||||
def write_BOTTOM( self, request ):
|
||||
request.write( "</body></html>" )
|
||||
@@ -0,0 +1,81 @@
|
||||
from twisted.web import resource
|
||||
from twisted.web.server import NOT_DONE_YET
|
||||
|
||||
from xen.xend.XendClient import server as XendServer
|
||||
from xen.xend import sxp
|
||||
|
||||
from HTMLBase import HTMLBase
|
||||
|
||||
from xen.xend.sv import DomList, NodeInfo, DomInfo
|
||||
|
||||
class Main( HTMLBase ):
|
||||
|
||||
isLeaf = True
|
||||
|
||||
def __init__( self ):
|
||||
HTMLBase.__init__(self)
|
||||
|
||||
def render_POST( self, request ):
|
||||
return self.render_GET( request )
|
||||
|
||||
def mainUrlWriter( self, s ):
|
||||
return "Main.rpy?%s" % s
|
||||
|
||||
def write_BODY( self, request, callback ):
|
||||
|
||||
self.callback = callback
|
||||
|
||||
request.write( "\n<table style='border:0px solid black; background: url(images/orb_01.jpg) no-repeat' cellspacing='0' cellpadding='0' border='0' width='780px' height='536px'>\n" )
|
||||
request.write( "<tr>\n" )
|
||||
request.write( " <td width='15px'> </td>" )
|
||||
request.write( " <td width='175px' align='center' valign'center'>" )
|
||||
request.write( " <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
|
||||
request.write( " <tr><td height='200px' align='center' valign='center'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
|
||||
request.write( " <img src='images/xen.png' width='150' height='75' border='0'/></a></td></tr>" )
|
||||
request.write( " <tr><td align='center' valign='top'>" )
|
||||
|
||||
request.write( " <p class='small'><a href='Main.rpy?mod=node'>Node details</a></p>" )
|
||||
request.write( " <p class='small'><a href='Main.rpy?mod=list'>Domains summary</a></p>" )
|
||||
|
||||
DomList.DomList( self.mainUrlWriter, self.continue_BODY ).write_BODY( request, True, False )
|
||||
|
||||
return NOT_DONE_YET
|
||||
|
||||
def continue_BODY( self, request ):
|
||||
request.write( " </td></tr>" )
|
||||
request.write( " </table>" )
|
||||
request.write( " " )
|
||||
request.write( " </td>\n" )
|
||||
request.write( " <td width='15px'> </td>" )
|
||||
request.write( " <td width='558px' align='left' valign='top'>" )
|
||||
request.write( " <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
|
||||
request.write( " <tr><td height='20px'></td></tr>" )
|
||||
request.write( " <tr><td align='center' valign='top'>" )
|
||||
|
||||
mod = request.args.get('mod')
|
||||
|
||||
if mod is None or len(mod) != 1:
|
||||
request.write( '<p>Please select a module</p>' )
|
||||
self.finish_BODY( request )
|
||||
elif mod[0] == 'info':
|
||||
DomInfo.DomInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
|
||||
elif mod[0] == 'list':
|
||||
DomList.DomList( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
|
||||
elif mod[0] == 'node':
|
||||
NodeInfo.NodeInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
|
||||
else:
|
||||
request.write( '<p>Invalid module. Please select another</p>' )
|
||||
self.finish_BODY( request )
|
||||
|
||||
def finish_BODY( self, request ):
|
||||
|
||||
request.write( " </td></tr>" )
|
||||
request.write( " </table>" )
|
||||
request.write( " </td>\n" )
|
||||
request.write( " <td width='17px'> </td>" )
|
||||
request.write( "</tr>\n" )
|
||||
|
||||
request.write( "</table>\n" )
|
||||
|
||||
self.callback( request )
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from xen.xend.sv.Main import *
|
||||
|
||||
resource = Main()
|
||||
@@ -0,0 +1,47 @@
|
||||
from xen.xend import XendDmesg
|
||||
from xen.xend import XendNode
|
||||
|
||||
from xen.xend.sv.util import *
|
||||
from xen.xend.sv.GenTabbed import *
|
||||
from xen.xend.sv.HTMLBase import HTMLBase
|
||||
|
||||
class NodeInfo( GenTabbed ):
|
||||
|
||||
def __init__( self, urlWriter, callback ):
|
||||
|
||||
def newUrlWriter( url ):
|
||||
return urlWriter( "mod=node%s" % url )
|
||||
|
||||
GenTabbed.__init__( self, newUrlWriter, [ 'General', 'Dmesg' ], [ NodeGeneralTab, NodeDmesgTab ], callback )
|
||||
|
||||
class NodeGeneralTab( GeneralTab ):
|
||||
|
||||
def __init__( self ):
|
||||
|
||||
nodeInfo = XendNode.instance().info()
|
||||
|
||||
dictNodeInfo = {}
|
||||
|
||||
for l in nodeInfo:
|
||||
dictNodeInfo[ l[0] ] = l[1]
|
||||
|
||||
dictTitles = {}
|
||||
dictTitles[ 'System' ] = 'system'
|
||||
dictTitles[ 'Hostname' ] = 'host'
|
||||
dictTitles[ 'Release' ] = 'release'
|
||||
dictTitles[ 'Version' ] ='version'
|
||||
dictTitles[ 'Machine' ] = 'machine'
|
||||
dictTitles[ 'Cores' ] = 'cores'
|
||||
dictTitles[ 'Hyperthreading' ] = ( 'hyperthreads_per_core', hyperthreadFormatter )
|
||||
dictTitles[ 'CPU Speed' ] = ( 'cpu_mhz', cpuFormatter )
|
||||
dictTitles[ 'Memory' ] = ( 'memory', memoryFormatter )
|
||||
dictTitles[ 'Free Memory' ] = ( 'free_memory', memoryFormatter )
|
||||
|
||||
GeneralTab.__init__( self, title="General Node Info", dict=dictNodeInfo, titles=dictTitles )
|
||||
|
||||
class NodeDmesgTab( PreTab ):
|
||||
|
||||
def __init__( self ):
|
||||
self.xd = XendDmesg.instance()
|
||||
PreTab.__init__( self, self.xd.info()[0] )
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from xen.xend.sv.HTMLBase import HTMLBase
|
||||
|
||||
class TabView( HTMLBase ):
|
||||
|
||||
def __init__( self, tab, tabs, urlWriter ):
|
||||
HTMLBase.__init__(self)
|
||||
self.tab = tab # interger - tab id
|
||||
self.tabs = tabs
|
||||
self.urlWriter = urlWriter
|
||||
|
||||
def write_BODY( self, request ):
|
||||
request.write( "<table style='' border='0' cellspacing='0' cellpadding='0' align='center'>" )
|
||||
request.write( "<tr height='22'>" )
|
||||
|
||||
if self.tab == 0:
|
||||
image = "left-end-highlight.jpg"
|
||||
else:
|
||||
image = "left-end-no-highlight.jpg"
|
||||
|
||||
request.write( "<td height='22' width='14'><image src='images/%s' width='14' height='22'></td>" % image )
|
||||
|
||||
count = len( self.tabs )
|
||||
|
||||
for i in range( count ):
|
||||
|
||||
if i == self.tab:
|
||||
image = "middle-highlight.jpg"
|
||||
else:
|
||||
image = "middle-no-highlight.jpg"
|
||||
|
||||
request.write( "<td style='background: url(images/%s)'><p align='center'><a href='%s'>%s</a></p></td>" % ( image, self.urlWriter( "&tab=%s" % i ), self.tabs[ i ] ) )
|
||||
|
||||
if i < count-1:
|
||||
if i == self.tab:
|
||||
image = "seperator-left-highlight.jpg"
|
||||
elif self.tab == i+1:
|
||||
image = "seperator-right-highlight.jpg"
|
||||
else:
|
||||
image = "seperator.jpg"
|
||||
|
||||
request.write( "<td height='22' width='23'><image src='images/%s' width='23' height='22'></td>" % image )
|
||||
|
||||
if self.tab == count - 1:
|
||||
image = "right-end-highlight.jpg"
|
||||
else:
|
||||
image = "right-end-no-highlight.jpg"
|
||||
|
||||
request.write( "<td height='22' width='14'><image src='images/%s' width='14' height='22'></td>" % image )
|
||||
request.write( "</tr></table>" )
|
||||
@@ -0,0 +1,363 @@
|
||||
# Copyright (C) 2004 Tom Wilkie <tw275@cam.ac.uk>
|
||||
# Copyright (C) 2004 Mike Wray
|
||||
"""Client API for the HTTP interface on xend.
|
||||
Callable as a script - see main().
|
||||
|
||||
This API is the 'control-plane' for xend.
|
||||
The 'data-plane' is done separately. For example, consoles
|
||||
are accessed via sockets on xend, but the list of consoles
|
||||
is accessible via this API.
|
||||
|
||||
This one is similar to mikes, but works in an async fashion
|
||||
"""
|
||||
import sys
|
||||
import httplib
|
||||
import types
|
||||
from StringIO import StringIO
|
||||
import urlparse
|
||||
|
||||
from xen.xend.encode import *
|
||||
from xen.xend.sxp import *
|
||||
from xen.xend.PrettyPrint import prettyprint
|
||||
|
||||
from twisted.protocols.http import HTTPClient
|
||||
from twisted.internet.protocol import ClientCreator
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.internet import reactor
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
class XendRequest( HTTPClient ):
|
||||
def __init__(self, deferred, urls):
|
||||
self.urls = urls
|
||||
self.deferred = deferred
|
||||
|
||||
def connectionMade(self):
|
||||
self.sendCommand('GET', self.urls[2])
|
||||
self.sendHeader('Host', '%s:%d' % (self.urls[0], self.urls[1]) )
|
||||
self.endHeaders()
|
||||
|
||||
def handleResponse(self, data):
|
||||
self.deferred.callback( data )
|
||||
|
||||
def process_SXP( sexp ):
|
||||
pin = Parser()
|
||||
pin.input(sexp)
|
||||
pin.input_eof()
|
||||
return pin.get_val()
|
||||
|
||||
def xend_request(url, method, data=None):
|
||||
"""Make a request to xend.
|
||||
|
||||
url xend request url
|
||||
method http method: POST or GET
|
||||
data request argument data (dict)
|
||||
"""
|
||||
urlinfo = urlparse.urlparse(url)
|
||||
(uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
|
||||
(hdr, args) = encode_data(data)
|
||||
if data and method == 'GET':
|
||||
upath += '?' + args
|
||||
args = None
|
||||
if method == "POST" and upath.endswith('/'):
|
||||
upath = upath[:-1]
|
||||
|
||||
deferred = Deferred()
|
||||
|
||||
clientCreator = ClientCreator( reactor, XendRequest, deferred, (ulocation, 8000, upath) )
|
||||
clientCreator.connectTCP( ulocation, 8000 )
|
||||
|
||||
deferred.addCallback( process_SXP )
|
||||
|
||||
return deferred
|
||||
|
||||
class XendError(RuntimeError):
|
||||
pass
|
||||
|
||||
class Foo(httplib.HTTPResponse):
|
||||
|
||||
def begin(self):
|
||||
fin = self.fp
|
||||
while(1):
|
||||
buf = fin.readline()
|
||||
print "***", buf
|
||||
if buf == '':
|
||||
print
|
||||
sys.exit()
|
||||
|
||||
|
||||
def sxprio(sxpr):
|
||||
"""Convert an sxpr to a string.
|
||||
"""
|
||||
io = StringIO()
|
||||
sxp.show(sxpr, out=io)
|
||||
print >> io
|
||||
io.seek(0)
|
||||
return io
|
||||
|
||||
def fileof(val):
|
||||
"""Converter for passing configs.
|
||||
Handles lists, files directly.
|
||||
Assumes a string is a file name and passes its contents.
|
||||
"""
|
||||
if isinstance(val, types.ListType):
|
||||
return sxprio(val)
|
||||
if isinstance(val, types.StringType):
|
||||
return file(val)
|
||||
if hasattr(val, 'readlines'):
|
||||
return val
|
||||
|
||||
# todo: need to sort of what urls/paths are using for objects.
|
||||
# e.g. for domains at the moment return '0'.
|
||||
# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
|
||||
# As an arg, assume abs path is obj uri, otherwise just id.
|
||||
|
||||
# Function to convert to full url: Xend.uri(path), e.g.
|
||||
# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
|
||||
# And should accept urls for ids?
|
||||
|
||||
def urljoin(location, root, prefix='', rest=''):
|
||||
prefix = str(prefix)
|
||||
rest = str(rest)
|
||||
base = 'http://' + location + root + prefix
|
||||
url = urlparse.urljoin(base, rest)
|
||||
return url
|
||||
|
||||
def nodeurl(location, root, id=''):
|
||||
return urljoin(location, root, 'node/', id)
|
||||
|
||||
def domainurl(location, root, id=''):
|
||||
return urljoin(location, root, 'domain/', id)
|
||||
|
||||
def consoleurl(location, root, id=''):
|
||||
return urljoin(location, root, 'console/', id)
|
||||
|
||||
def deviceurl(location, root, id=''):
|
||||
return urljoin(location, root, 'device/', id)
|
||||
|
||||
def vneturl(location, root, id=''):
|
||||
return urljoin(location, root, 'vnet/', id)
|
||||
|
||||
def eventurl(location, root, id=''):
|
||||
return urljoin(location, root, 'event/', id)
|
||||
|
||||
def xend_get(url, args=None):
|
||||
"""Make a xend request using GET.
|
||||
Requests using GET are 'safe' and may be repeated without
|
||||
nasty side-effects.
|
||||
"""
|
||||
return xend_request(url, "GET", args)
|
||||
|
||||
def xend_call(url, data):
|
||||
"""Make xend request using POST.
|
||||
Requests using POST potentially cause side-effects and should
|
||||
not be repeated unless it really is wanted to do the side
|
||||
effect again.
|
||||
"""
|
||||
return xend_request(url, "POST", data)
|
||||
|
||||
class Xend:
|
||||
|
||||
"""Default location of the xend server."""
|
||||
SRV_DEFAULT = "localhost"
|
||||
|
||||
"""Default path to the xend root on the server."""
|
||||
ROOT_DEFAULT = "/xend/"
|
||||
|
||||
def __init__(self, srv=None, root=None):
|
||||
self.bind(srv, root)
|
||||
|
||||
def bind(self, srv=None, root=None):
|
||||
"""Bind to a given server.
|
||||
|
||||
srv server location (host:port)
|
||||
root server xend root path
|
||||
"""
|
||||
if srv is None: srv = self.SRV_DEFAULT
|
||||
if root is None: root = self.ROOT_DEFAULT
|
||||
if not root.endswith('/'): root += '/'
|
||||
self.location = srv
|
||||
self.root = root
|
||||
|
||||
def nodeurl(self, id=''):
|
||||
return nodeurl(self.location, self.root, id)
|
||||
|
||||
def domainurl(self, id=''):
|
||||
return domainurl(self.location, self.root, id)
|
||||
|
||||
def consoleurl(self, id=''):
|
||||
return consoleurl(self.location, self.root, id)
|
||||
|
||||
def deviceurl(self, id=''):
|
||||
return deviceurl(self.location, self.root, id)
|
||||
|
||||
def vneturl(self, id=''):
|
||||
return vneturl(self.location, self.root, id)
|
||||
|
||||
def eventurl(self, id=''):
|
||||
return eventurl(self.location, self.root, id)
|
||||
|
||||
def xend(self):
|
||||
return xend_get(urljoin(self.location, self.root))
|
||||
|
||||
def xend_node(self):
|
||||
return xend_get(self.nodeurl())
|
||||
|
||||
def xend_node_cpu_rrobin_slice_set(self, slice):
|
||||
return xend_call(self.nodeurl(),
|
||||
{'op' : 'cpu_rrobin_slice_set',
|
||||
'slice' : slice })
|
||||
|
||||
def xend_node_cpu_bvt_slice_set(self, ctx_allow):
|
||||
return xend_call(self.nodeurl(),
|
||||
{'op' : 'cpu_bvt_slice_set',
|
||||
'ctx_allow' : ctx_allow })
|
||||
|
||||
def xend_node_cpu_fbvt_slice_set(self, ctx_allow):
|
||||
return xend_call(self.nodeurl(),
|
||||
{'op' : 'cpu_fbvt_slice_set',
|
||||
'ctx_allow' : ctx_allow })
|
||||
|
||||
def xend_domains(self):
|
||||
return xend_get(self.domainurl())
|
||||
|
||||
def xend_domain_create(self, conf):
|
||||
return xend_call(self.domainurl(),
|
||||
{'op' : 'create',
|
||||
'config' : fileof(conf) })
|
||||
|
||||
def xend_domain(self, id):
|
||||
return xend_get(self.domainurl(id))
|
||||
|
||||
def xend_domain_unpause(self, id):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'unpause'})
|
||||
|
||||
def xend_domain_pause(self, id):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'pause'})
|
||||
|
||||
def xend_domain_shutdown(self, id, reason):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'shutdown',
|
||||
'reason' : reason })
|
||||
|
||||
def xend_domain_destroy(self, id):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'destroy'})
|
||||
|
||||
def xend_domain_save(self, id, filename):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'save',
|
||||
'file' : filename})
|
||||
|
||||
def xend_domain_restore(self, id, filename):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'restore',
|
||||
'file' : filename })
|
||||
|
||||
def xend_domain_migrate(self, id, dst):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'migrate',
|
||||
'destination': dst})
|
||||
|
||||
def xend_domain_pincpu(self, id, cpu):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'pincpu',
|
||||
'cpu' : cpu})
|
||||
|
||||
def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'cpu_bvt_set',
|
||||
'mcuadv' : mcuadv,
|
||||
'warp' : warp,
|
||||
'warpl' : warpl,
|
||||
'warpu' : warpu })
|
||||
|
||||
def xend_domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'cpu_fbvt_set',
|
||||
'mcuadv' : mcuadv,
|
||||
'warp' : warp,
|
||||
'warpl' : warpl,
|
||||
'warpu' : warpu })
|
||||
|
||||
|
||||
def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'cpu_atropos_set',
|
||||
'period' : period,
|
||||
'slice' : slice,
|
||||
'latency' : latency,
|
||||
'xtratime': xtratime })
|
||||
|
||||
def xend_domain_vifs(self, id):
|
||||
return xend_get(self.domainurl(id),
|
||||
{ 'op' : 'vifs' })
|
||||
|
||||
def xend_domain_vif_ip_add(self, id, vif, ipaddr):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'vif_ip_add',
|
||||
'vif' : vif,
|
||||
'ip' : ipaddr })
|
||||
|
||||
def xend_domain_vbds(self, id):
|
||||
return xend_get(self.domainurl(id),
|
||||
{'op' : 'vbds'})
|
||||
|
||||
def xend_domain_vbd(self, id, vbd):
|
||||
return xend_get(self.domainurl(id),
|
||||
{'op' : 'vbd',
|
||||
'vbd' : vbd})
|
||||
|
||||
def xend_consoles(self):
|
||||
return xend_get(self.consoleurl())
|
||||
|
||||
def xend_console(self, id):
|
||||
return xend_get(self.consoleurl(id))
|
||||
|
||||
def xend_vnets(self):
|
||||
return xend_get(self.vneturl())
|
||||
|
||||
def xend_vnet_create(self, conf):
|
||||
return xend_call(self.vneturl(),
|
||||
{'op': 'create', 'config': fileof(conf) })
|
||||
|
||||
def xend_vnet(self, id):
|
||||
return xend_get(self.vneturl(id))
|
||||
|
||||
def xend_vnet_delete(self, id):
|
||||
return xend_call(self.vneturl(id),
|
||||
{'op': 'delete'})
|
||||
|
||||
def xend_event_inject(self, sxpr):
|
||||
val = xend_call(self.eventurl(),
|
||||
{'op': 'inject', 'event': fileof(sxpr) })
|
||||
|
||||
def main(argv):
|
||||
"""Call an API function:
|
||||
|
||||
python XendClient.py fn args...
|
||||
|
||||
The leading 'xend_' on the function can be omitted.
|
||||
Example:
|
||||
|
||||
> python XendClient.py domains
|
||||
(domain 0 8)
|
||||
> python XendClient.py domain 0
|
||||
(domain (id 0) (name Domain-0) (memory 128))
|
||||
"""
|
||||
server = Xend()
|
||||
fn = argv[1]
|
||||
if not fn.startswith('xend'):
|
||||
fn = 'xend_' + fn
|
||||
args = argv[2:]
|
||||
deferred = getattr(server, fn)(*args)
|
||||
deferred.addCallback( prettyprint )
|
||||
reactor.run()
|
||||
print
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
else:
|
||||
server = Xend()
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 535 B |
|
After Width: | Height: | Size: 440 B |
|
After Width: | Height: | Size: 376 B |
|
After Width: | Height: | Size: 344 B |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 507 B |
|
After Width: | Height: | Size: 535 B |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 552 B |
|
After Width: | Height: | Size: 560 B |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,30 @@
|
||||
|
||||
P {font-family: verdana, arial; font-size: 12px; color: black}
|
||||
.small {font-size: 10px}
|
||||
|
||||
TD.domainInfo {font-family: verdana, arial; font-size: 10px; color: black}
|
||||
TD.domainInfoHead {font-family: verdana, arial; font-size: 10px; color: white; font-face: bold}
|
||||
|
||||
TD.domainInfoHead {background-color: black}
|
||||
TR.domainInfoOdd {background-color: white}
|
||||
TR.domainInfoEven {background-color: lightgrey}
|
||||
|
||||
body {
|
||||
width: 670px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
background-color: #fff;
|
||||
background-image: url(../images/orb_02.jpg);
|
||||
background-repeat: repeat-y;
|
||||
background-position: left top;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
letter-spacing: 0px;
|
||||
scrollbar-base-color: #333333;
|
||||
scrollbar-track-color: #666666;
|
||||
scrollbar-face-color: #fff;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
from xen.xend.sv.XendClientDeferred import server
|
||||
from xen.xend import sxp
|
||||
|
||||
def getDomInfoHash( domain ):
|
||||
deferred = server.xend_domain( int( domain ) )
|
||||
deferred.addCallback( procDomInfo, domain )
|
||||
return deferred
|
||||
|
||||
def procDomInfo( domInfo, domain ):
|
||||
d = {}
|
||||
d['dom'] = int( domain )
|
||||
d['name'] = sxp.child_value( domInfo, 'name' )
|
||||
d['mem'] = int( sxp.child_value( domInfo, 'memory' ) )
|
||||
d['cpu'] = int( sxp.child_value( domInfo, 'cpu' ) )
|
||||
d['state'] = sxp.child_value( domInfo, 'state' )
|
||||
d['cpu_time'] = float( sxp.child_value( domInfo, 'cpu_time' ) )
|
||||
if( sxp.child_value( domInfo, 'up_time' ) ):
|
||||
d['up_time'] = float( sxp.child_value( domInfo, 'up_time' ) )
|
||||
if( sxp.child_value( domInfo, 'start_time' ) ):
|
||||
d['start_time'] = float( sxp.child_value( domInfo, 'start_time' ) )
|
||||
return d
|
||||
|
||||
def bigTimeFormatter( time ):
|
||||
weeks = time // 604800
|
||||
remainder = time % 604800
|
||||
days = remainder // 86400
|
||||
|
||||
remainder = remainder % 86400
|
||||
|
||||
hms = smallTimeFormatter( remainder )
|
||||
|
||||
return "%d weeks, %d days, %s" % ( weeks, days, hms )
|
||||
|
||||
def smallTimeFormatter( time ):
|
||||
hours = time // 3600
|
||||
remainder = time % 3600
|
||||
mins = remainder // 60
|
||||
secs = time % 60
|
||||
return "%02d:%02d:%04.1f (hh:mm:ss.s)" % ( hours, mins, secs )
|
||||
|
||||
def stateFormatter( state ):
|
||||
states = [ 'Running', 'Blocked', 'Paused', 'Shutdown', 'Crashed' ]
|
||||
|
||||
for i in range( len( state ) ):
|
||||
if state[i] != "-":
|
||||
return states[ i ] + " (%s)" % state
|
||||
|
||||
return state
|
||||
|
||||
def memoryFormatter( mem ):
|
||||
return "%7dMb" % mem
|
||||
|
||||
def cpuFormatter( mhz ):
|
||||
if mhz > 1000:
|
||||
ghz = float( mhz ) / 1000.0
|
||||
return "%4.2fGHz" % ghz
|
||||
else:
|
||||
return "%4dMHz" % mhz
|
||||
|
||||
def hyperthreadFormatter( threads ):
|
||||
if int( threads ) > 1:
|
||||
return "Yes (%d)" % threads
|
||||
else:
|
||||
return "No"
|
||||
@@ -105,8 +105,23 @@ class Xm:
|
||||
|
||||
def getprog(self, name, val=None):
|
||||
"""Get a sub-program.
|
||||
name Name of the sub-program (or optionally, an unambiguous
|
||||
prefix of its name)
|
||||
val Default return value if no (unique) match is found
|
||||
"""
|
||||
return self.progs.get(name, val)
|
||||
|
||||
match = None
|
||||
for progname in self.progs.keys():
|
||||
if progname == name:
|
||||
match = progname
|
||||
break
|
||||
if progname.startswith(name):
|
||||
if not match:
|
||||
match = progname
|
||||
else:
|
||||
return val # name is ambiguous - bail out
|
||||
|
||||
return self.progs.get(match, val)
|
||||
|
||||
def proglist(self):
|
||||
"""Get a list of sub-programs, ordered by group.
|
||||
|
||||
@@ -840,7 +840,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
|
||||
|
||||
if ( unlikely((e = percpu_info[cpu].gps) == NULL) )
|
||||
{
|
||||
MEM_LOG("No GPS to reassign pfn %08lx to\n", pfn);
|
||||
MEM_LOG("No GPS to reassign pfn %08lx to", pfn);
|
||||
okay = 0;
|
||||
break;
|
||||
}
|
||||
@@ -865,6 +865,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
|
||||
if ( unlikely(test_bit(DF_DYING, &e->flags)) ||
|
||||
unlikely(IS_XEN_HEAP_FRAME(page)) )
|
||||
{
|
||||
MEM_LOG("Reassignment page is Xen heap, or dest dom is dying.");
|
||||
okay = 0;
|
||||
goto reassign_fail;
|
||||
}
|
||||
@@ -1051,8 +1052,8 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
|
||||
* If in log-dirty mode, mark the corresponding pseudo-physical
|
||||
* page as dirty.
|
||||
*/
|
||||
if( unlikely(current->mm.shadow_mode == SHM_logdirty) )
|
||||
mark_dirty( ¤t->mm, pfn );
|
||||
if ( unlikely(current->mm.shadow_mode == SHM_logdirty) )
|
||||
mark_dirty(¤t->mm, pfn);
|
||||
|
||||
put_page(&frame_table[pfn]);
|
||||
break;
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#include <xen/perfc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
/* Make the scary benign errors go away. */
|
||||
#undef DPRINTK
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
|
||||
/*
|
||||
* Obtain the base and limit associated with the given segment selector.
|
||||
* The selector must identify a 32-bit code or data segment. Any segment that
|
||||
@@ -495,9 +499,34 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
goto undecodeable;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
char str1[] = { 0x65,0x8b,0x00,0x8b,0x30 };
|
||||
char str2[] = { 0x65,0x8b,0x02,0x8b,0x40,0x0c };
|
||||
char str3[] = { 0x65,0x8b,0x30,0x85,0xf6 };
|
||||
char str4[] = { 0x65,0x8b,0x00,0x5d,0x8b,0x00 };
|
||||
char str5[] = { 0x65,0x89,0x30,0x8b,0x45,0x08 };
|
||||
char str6[] = { 0x65,0x8b,0x00,0x8b,0x50,0x0c };
|
||||
char str7[] = { 0x65,0x89,0x51,0x00,0x83,0xc8,0xff };
|
||||
if ( (memcmp(eip,str1,5) == 0) ||
|
||||
(memcmp(eip,str2,6) == 0) ) goto out;
|
||||
if ( (memcmp(eip,str3,5) == 0) ||
|
||||
(memcmp(eip,str4,6) == 0) ) goto out;
|
||||
if ( (memcmp(eip,str5,6) == 0) ||
|
||||
(memcmp(eip,str6,6) == 0) ) goto out;
|
||||
if ( (memcmp(eip,str7,7) == 0) ||
|
||||
(memcmp(eip,str7,7) == 0) ) goto out;
|
||||
}
|
||||
printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
|
||||
eip[-8],eip[-7],eip[-6],eip[-5],eip[-4],eip[-3],eip[-2],eip[-1]);
|
||||
printk(" .byte 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",
|
||||
eip[0],eip[1],eip[2],eip[3],eip[4],eip[5],eip[6],eip[7]);
|
||||
printk(" @ %04x:%08lx\n", regs->xcs, regs->eip);
|
||||
#endif
|
||||
|
||||
/* Success! */
|
||||
regs->eip += pb - eip;
|
||||
perfc_incrc(emulations);
|
||||
regs->eip += pb - eip;
|
||||
return 1;
|
||||
|
||||
undecodeable:
|
||||
@@ -530,5 +559,3 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||