aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python
diff options
context:
space:
mode:
Diffstat (limited to 'tools/python')
-rw-r--r--tools/python/setup.py1
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c107
-rw-r--r--tools/python/xen/lowlevel/xu/xu.c872
-rw-r--r--tools/python/xen/util/memmap.py41
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py137
-rw-r--r--tools/python/xen/xend/server/SrvDaemon.py18
-rw-r--r--tools/python/xen/xend/server/SrvUsbif.py249
-rwxr-xr-xtools/python/xen/xend/server/channel.py9
-rw-r--r--tools/python/xen/xend/server/messages.py68
-rwxr-xr-xtools/python/xen/xend/server/netif.py22
-rw-r--r--tools/python/xen/xend/server/usbif.py368
-rw-r--r--tools/python/xen/xm/create.py50
12 files changed, 1638 insertions, 304 deletions
diff --git a/tools/python/setup.py b/tools/python/setup.py
index 99069d0be4..81536989ee 100644
--- a/tools/python/setup.py
+++ b/tools/python/setup.py
@@ -10,6 +10,7 @@ extra_compile_args = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
include_dirs = [ XEN_ROOT + "/tools/python/xen/lowlevel/xu",
XEN_ROOT + "/tools/libxc",
XEN_ROOT + "/tools/libxutil",
+ XEN_ROOT + "/tools/xcs",
]
library_dirs = [ XEN_ROOT + "/tools/libxc",
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index d2b7da0eba..543a2cd380 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -16,6 +16,7 @@
#include <arpa/inet.h>
#include "xc_private.h"
#include "gzip_stream.h"
+#include "linux_boot_params.h"
/* Needed for Python versions earlier than 2.3. */
#ifndef PyMODINIT_FUNC
@@ -347,19 +348,19 @@ static PyObject *pyxc_linux_build(PyObject *self,
u32 dom;
char *image, *ramdisk = NULL, *cmdline = "";
- int control_evtchn, flags = 0;
+ int control_evtchn, flags = 0, vcpus = 1;
static char *kwd_list[] = { "dom", "control_evtchn",
- "image", "ramdisk", "cmdline", "flags",
+ "image", "ramdisk", "cmdline", "flags", "vcpus",
NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssii", kwd_list,
&dom, &control_evtchn,
- &image, &ramdisk, &cmdline, &flags) )
+ &image, &ramdisk, &cmdline, &flags, &vcpus) )
return NULL;
if ( xc_linux_build(xc->xc_handle, dom, image,
- ramdisk, cmdline, control_evtchn, flags) != 0 )
+ ramdisk, cmdline, control_evtchn, flags, vcpus) != 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
@@ -393,6 +394,90 @@ static PyObject *pyxc_plan9_build(PyObject *self,
return zero;
}
+static PyObject *pyxc_vmx_build(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ XcObject *xc = (XcObject *)self;
+
+ u32 dom;
+ char *image, *ramdisk = NULL, *cmdline = "";
+ PyObject *memmap;
+ int control_evtchn, flags = 0;
+ int numItems, i;
+ int memsize;
+ struct mem_map mem_map;
+
+ static char *kwd_list[] = { "dom", "control_evtchn",
+ "memsize",
+ "image", "memmap",
+ "ramdisk", "cmdline", "flags",
+ NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiisO!|ssi", kwd_list,
+ &dom, &control_evtchn,
+ &memsize,
+ &image, &PyList_Type, &memmap,
+ &ramdisk, &cmdline, &flags) )
+ return NULL;
+
+ memset(&mem_map, 0, sizeof(mem_map));
+ /* Parse memmap */
+
+ /* get the number of lines passed to us */
+ numItems = PyList_Size(memmap) - 1; /* removing the line
+ containing "memmap" */
+ printf ("numItems: %d\n", numItems);
+ mem_map.nr_map = numItems;
+
+
+ /* should raise an error here. */
+ if (numItems < 0) return NULL; /* Not a list */
+
+
+ /* iterate over items of the list, grabbing ranges and parsing them */
+ for (i = 1; i <= numItems; i++) { // skip over "memmap"
+ PyObject *item, *f1, *f2, *f3, *f4;
+ int numFields;
+ unsigned long lf1, lf2, lf3, lf4;
+ char *sf1, *sf2;
+
+ /* grab the string object from the next element of the list */
+ item = PyList_GetItem(memmap, i); /* Can't fail */
+
+ /* get the number of lines passed to us */
+ numFields = PyList_Size(item);
+
+ if (numFields != 4)
+ return NULL;
+
+ f1 = PyList_GetItem(item, 0);
+ f2 = PyList_GetItem(item, 1);
+ f3 = PyList_GetItem(item, 2);
+ f4 = PyList_GetItem(item, 3);
+
+ /* Convert objects to strings/longs */
+ sf1 = PyString_AsString(f1);
+ sf2 = PyString_AsString(f2);
+ lf3 = PyLong_AsLong(f3);
+ lf4 = PyLong_AsLong(f4);
+ sscanf(sf1, "%lx", &lf1);
+ sscanf(sf2, "%lx", &lf2);
+
+ mem_map.map[i-1].addr = lf1;
+ mem_map.map[i-1].size = lf2 - lf1;
+ mem_map.map[i-1].type = lf3;
+ mem_map.map[i-1].caching_attr = lf4;
+ }
+
+ if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, &mem_map,
+ ramdisk, cmdline, control_evtchn, flags) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
static PyObject *pyxc_bvtsched_global_set(PyObject *self,
PyObject *args,
PyObject *kwds)
@@ -941,6 +1026,18 @@ static PyMethodDef pyxc_methods[] = {
" image [str]: Name of kernel image file. May be gzipped.\n"
" ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
" cmdline [str, n/a]: Kernel parameters, if any.\n\n"
+ " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "vmx_build",
+ (PyCFunction)pyxc_vmx_build,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Build a new Linux guest OS.\n"
+ " dom [int]: Identifier of domain to build into.\n"
+ " image [str]: Name of kernel image file. May be gzipped.\n"
+ " memmap [str]: Memory map.\n\n"
+ " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
+ " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "bvtsched_global_set",
diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c
index 9a67693683..12f27d63db 100644
--- a/tools/python/xen/lowlevel/xu/xu.c
+++ b/tools/python/xen/lowlevel/xu/xu.c
@@ -59,6 +59,7 @@
/* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
* to check for errors. */
+/*
static void set_cloexec(int fd)
{
int flags = fcntl(fd, F_GETFD, 0);
@@ -69,7 +70,183 @@ static void set_cloexec(int fd)
flags |= FD_CLOEXEC;
fcntl(fd, F_SETFD, flags);
}
+*/
+/*
+ * *********************** XCS INTERFACE ***********************
+ */
+
+#include <arpa/inet.h>
+#include <xcs_proto.h>
+
+static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
+static int xcs_data_fd = -1; /* data connection to the xcs server. */
+static u32 xcs_session_id = 0;
+static int xcs_ctrl_send(xcs_msg_t *msg);
+static int xcs_ctrl_read(xcs_msg_t *msg);
+static int xcs_data_send(xcs_msg_t *msg);
+static int xcs_data_read(xcs_msg_t *msg);
+
+static int xcs_connect(char *ip, short port)
+{
+ struct sockaddr_in addr;
+ int ret, flags;
+ xcs_msg_t msg;
+
+ if (xcs_data_fd != -1) /* already connected */
+ return 0;
+
+ xcs_ctrl_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (xcs_ctrl_fd < 0)
+ {
+ printf("error creating xcs socket!\n");
+ goto fail;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = inet_addr(ip);
+ memset(&(addr.sin_zero), '\0', 8);
+
+ ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr));
+ if (ret < 0)
+ {
+ printf("error connecting to xcs(ctrl)! (%d)\n", errno);
+ goto ctrl_fd_fail;
+ }
+
+ //set_cloexec(xcs_ctrl_fd);
+
+ msg.type = XCS_CONNECT_CTRL;
+ msg.u.connect.session_id = xcs_session_id;
+ xcs_ctrl_send(&msg);
+ xcs_ctrl_read(&msg); /* TODO: timeout + error! */
+
+ if (msg.result != XCS_RSLT_OK)
+ {
+ printf("error connecting xcs control channel!\n");
+ goto ctrl_fd_fail;
+ }
+ xcs_session_id = msg.u.connect.session_id;
+
+ /* now the data connection. */
+ xcs_data_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (xcs_data_fd < 0)
+ {
+ printf("error creating xcs data socket!\n");
+ goto ctrl_fd_fail;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = inet_addr(ip);
+ memset(&(addr.sin_zero), '\0', 8);
+
+ ret = connect(xcs_data_fd, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr));
+ if (ret < 0)
+ {
+ printf("error connecting to xcs(data)! (%d)\n", errno);
+ goto data_fd_fail;
+ }
+
+ //set_cloexec(xcs_data_fd);
+ msg.type = XCS_CONNECT_DATA;
+ msg.u.connect.session_id = xcs_session_id;
+ xcs_data_send(&msg);
+ xcs_data_read(&msg); /* TODO: timeout + error! */
+
+ if (msg.result != XCS_RSLT_OK)
+ {
+ printf("error connecting xcs control channel!\n");
+ goto ctrl_fd_fail;
+ }
+
+ if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
+ (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
+ {
+ printf("Unable to set non-blocking status on data socket.");
+ goto data_fd_fail;
+ }
+
+ return 0;
+
+data_fd_fail:
+ close(xcs_data_fd);
+ xcs_data_fd = -1;
+
+ctrl_fd_fail:
+ close(xcs_ctrl_fd);
+ xcs_ctrl_fd = -1;
+
+fail:
+ return -1;
+
+}
+
+static void xcs_disconnect(void)
+{
+ close(xcs_data_fd);
+ xcs_data_fd = -1;
+ close(xcs_ctrl_fd);
+ xcs_ctrl_fd = -1;
+}
+
+static int xcs_ctrl_read(xcs_msg_t *msg)
+{
+ int ret;
+
+ ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
+ return ret;
+}
+
+static int xcs_ctrl_send(xcs_msg_t *msg)
+{
+ int ret;
+
+ ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
+ return ret;
+}
+
+static int xcs_data_read(xcs_msg_t *msg)
+{
+ int ret;
+
+ ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
+ return ret;
+}
+
+static int xcs_data_send(xcs_msg_t *msg)
+{
+ int ret;
+
+ ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
+ return ret;
+}
+
+
+typedef struct kme_st {
+ xcs_msg_t msg;
+ struct kme_st *next;
+} xcs_msg_ent_t;
+
+
+#define XCS_RING_SIZE 64
+static xcs_msg_ent_t *req_ring[64];
+static unsigned req_prod = 0;
+static unsigned req_cons = 0;
+
+static xcs_msg_ent_t *rsp_ring[64];
+static unsigned rsp_prod = 0;
+static unsigned rsp_cons = 0;
+
+#define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
+#define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE])
+#define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
+#define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
+#define REQ_RING_EMPTY ( req_prod == req_cons )
+#define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
/*
* *********************** NOTIFIER ***********************
*/
@@ -81,81 +258,136 @@ typedef struct {
static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- u16 v;
- int bytes;
+ xcs_msg_ent_t *ent;
+ int ret;
if ( !PyArg_ParseTuple(args, "") )
return NULL;
-
- while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+
+ while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
{
- if ( errno == EINTR )
+ ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
+ ret = xcs_data_read(&ent->msg);
+
+ if (ret == -1)
+ {
+ free(ent);
+ if ( errno == EINTR )
+ continue;
+ if ( errno == EAGAIN )
+ break;
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ switch (ent->msg.type)
+ {
+ case XCS_REQUEST:
+ REQ_RING_ENT(req_prod) = ent;
+ req_prod++;
continue;
- if ( errno == EAGAIN )
- goto none;
- return PyErr_SetFromErrno(PyExc_IOError);
+
+ case XCS_RESPONSE:
+ RSP_RING_ENT(rsp_prod) = ent;
+ rsp_prod++;
+ continue;
+
+ case XCS_VIRQ:
+ ret = ent->msg.u.control.local_port;
+ free(ent);
+ return PyInt_FromLong(ret);
+
+ default:
+ /*printf("Throwing away xcs msg type: %u\n", ent->msg.type);*/
+ free(ent);
+ }
+ }
+
+ if (!REQ_RING_EMPTY)
+ {
+ return PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port);
+ }
+
+ if (!RSP_RING_EMPTY)
+ {
+ return PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port);
}
- if ( bytes == sizeof(v) )
- return PyInt_FromLong(v);
-
- none:
Py_INCREF(Py_None);
return Py_None;
}
+/* this is now a NOOP */
static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- u16 v;
- int idx;
-
- if ( !PyArg_ParseTuple(args, "i", &idx) )
- return NULL;
-
- v = (u16)idx;
-
- (void)write(xun->evtchn_fd, &v, sizeof(v));
-
Py_INCREF(Py_None);
return Py_None;
}
+/* this is now a NOOP */
static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- int idx;
-
- if ( !PyArg_ParseTuple(args, "i", &idx) )
- return NULL;
-
- if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
- return PyErr_SetFromErrno(PyExc_IOError);
-
Py_INCREF(Py_None);
return Py_None;
}
-static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+static PyObject *xu_notifier_bind_virq(PyObject *self,
+ PyObject *args, PyObject *kwds)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- int idx;
+ int virq;
+ xcs_msg_t kmsg;
- if ( !PyArg_ParseTuple(args, "i", &idx) )
+ static char *kwd_list[] = { "virq", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
return NULL;
+
+ kmsg.type = XCS_VIRQ_BIND;
+ kmsg.u.virq.virq = virq;
+ xcs_ctrl_send(&kmsg);
+ xcs_ctrl_read(&kmsg);
+
+ if ( kmsg.result != XCS_RSLT_OK )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyInt_FromLong(kmsg.u.virq.port);
+}
- if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
- return PyErr_SetFromErrno(PyExc_IOError);
+static PyObject *xu_notifier_virq_send(PyObject *self,
+ PyObject *args, PyObject *kwds)
+{
+ int port;
+ xcs_msg_t kmsg;
+ static char *kwd_list[] = { "port", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
+ return NULL;
+
+ kmsg.type = XCS_VIRQ;
+ kmsg.u.control.local_port = port;
+ xcs_ctrl_send(&kmsg);
+ xcs_ctrl_read(&kmsg);
+
+ if ( kmsg.result != XCS_RSLT_OK )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyInt_FromLong(kmsg.u.virq.port);
+}
+
+/* this is now a NOOP */
+static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
+{
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- return PyInt_FromLong(xun->evtchn_fd);
+ return PyInt_FromLong(xcs_data_fd);
}
static PyMethodDef xu_notifier_methods[] = {
@@ -178,6 +410,18 @@ static PyMethodDef xu_notifier_methods[] = {
(PyCFunction)xu_notifier_unbind,
METH_VARARGS,
"No longer get notifications for a @port.\n" },
+
+ { "bind_virq",
+ (PyCFunction)xu_notifier_bind_virq,
+ METH_VARARGS | METH_KEYWORDS,
+ "Get notifications for a virq.\n"
+ " virq [int]: VIRQ to bind.\n\n" },
+
+ { "virq_send",
+ (PyCFunction)xu_notifier_virq_send,
+ METH_VARARGS | METH_KEYWORDS,
+ "Fire a virq notification.\n"
+ " port [int]: port that VIRQ is bound to.\n\n" },
{ "fileno",
(PyCFunction)xu_notifier_fileno,
@@ -189,35 +433,22 @@ static PyMethodDef xu_notifier_methods[] = {
staticforward PyTypeObject xu_notifier_type;
+/* connect to xcs if we aren't already, and return a dummy object. */
static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
{
xu_notifier_object *xun;
- struct stat st;
+ int i;
if ( !PyArg_ParseTuple(args, "") )
return NULL;
xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
- /* Make sure any existing device file links to correct device. */
- if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
- !S_ISCHR(st.st_mode) ||
- (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
- (void)unlink(EVTCHN_DEV_NAME);
-
- reopen:
- xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
- if ( xun->evtchn_fd == -1 )
- {
- if ( (errno == ENOENT) &&
- ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
- (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
- makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
- goto reopen;
- PyObject_Del((PyObject *)xun);
- return PyErr_SetFromErrno(PyExc_IOError);
- }
- set_cloexec(xun->evtchn_fd);
+ for (i = 0; i < XCS_RING_SIZE; i++)
+ REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
+
+ (void)xcs_connect("127.0.0.1", XCS_TCP_PORT);
+
return (PyObject *)xun;
}
@@ -229,8 +460,7 @@ static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
static void xu_notifier_dealloc(PyObject *self)
{
- xu_notifier_object *xun = (xu_notifier_object *)self;
- (void)close(xun->evtchn_fd);
+ xcs_disconnect();
PyObject_Del(self);
}
@@ -287,6 +517,24 @@ static PyTypeObject xu_notifier_type = {
PyDict_SetItemString(dict, #_field, obj); \
} while ( 0 )
+#define PSTR2CHAR(_struct, _field) \
+ do { \
+ PyObject *obj; \
+ if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
+ { \
+ if ( PyString_Check(obj) ) \
+ { \
+ char *buffer = PyString_AsString(obj); \
+ \
+ strcpy(((_struct *)&xum->msg.msg[0])->_field, \
+ buffer); \
+ /* Should complain about length - think later */ \
+ dict_items_parsed++; \
+ } \
+ } \
+ xum->msg.length = sizeof(_struct); \
+ } while ( 0 )
+
typedef struct {
PyObject_HEAD;
control_msg_t msg;
@@ -478,6 +726,52 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
C2P(netif_be_driver_status_t, status, Int, Long);
return dict;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
+ C2P(usbif_fe_interface_status_changed_t, status, Int, Long);
+ C2P(usbif_fe_interface_status_changed_t, evtchn, Int, Long);
+ C2P(usbif_fe_interface_status_changed_t, domid, Int, Long);
+ C2P(usbif_fe_interface_status_changed_t, bandwidth, Int, Long);
+ C2P(usbif_fe_interface_status_changed_t, num_ports, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
+ C2P(usbif_fe_driver_status_changed_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
+ C2P(usbif_fe_interface_connect_t, shmem_frame, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
+ C2P(usbif_be_create_t, domid, Int, Long);
+ C2P(usbif_be_create_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
+ C2P(usbif_be_destroy_t, domid, Int, Long);
+ C2P(usbif_be_destroy_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
+ C2P(usbif_be_connect_t, domid, Int, Long);
+ C2P(usbif_be_connect_t, shmem_frame, Int, Long);
+ C2P(usbif_be_connect_t, evtchn, Int, Long);
+ C2P(usbif_be_connect_t, bandwidth, Int, Long);
+ C2P(usbif_be_connect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
+ C2P(usbif_be_disconnect_t, domid, Int, Long);
+ C2P(usbif_be_disconnect_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
+ C2P(usbif_be_driver_status_changed_t, status, Int, Long);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
+ C2P(usbif_be_claim_port_t, domid, Int, Long);
+ C2P(usbif_be_claim_port_t, usbif_port, Int, Long);
+ C2P(usbif_be_claim_port_t, status, Int, Long);
+ C2P(usbif_be_claim_port_t, path, String, String);
+ return dict;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
+ C2P(usbif_be_release_port_t, path, String, String);
+ return dict;
case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
C2P(mem_request_t, target, Int, Long);
C2P(mem_request_t, status, Int, Long);
@@ -623,6 +917,12 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
P2C(netif_be_create_t, mac[3], u8);
P2C(netif_be_create_t, mac[4], u8);
P2C(netif_be_create_t, mac[5], u8);
+ P2C(netif_be_create_t, be_mac[0], u8);
+ P2C(netif_be_create_t, be_mac[1], u8);
+ P2C(netif_be_create_t, be_mac[2], u8);
+ P2C(netif_be_create_t, be_mac[3], u8);
+ P2C(netif_be_create_t, be_mac[4], u8);
+ P2C(netif_be_create_t, be_mac[5], u8);
break;
case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
P2C(netif_be_destroy_t, domid, u32);
@@ -647,6 +947,53 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
P2C(mem_request_t, target, u32);
P2C(mem_request_t, status, u32);
break;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED):
+ P2C(usbif_fe_interface_status_changed_t, status, u32);
+ P2C(usbif_fe_interface_status_changed_t, evtchn, u16);
+ P2C(usbif_fe_interface_status_changed_t, domid, domid_t);
+ P2C(usbif_fe_interface_status_changed_t, bandwidth, u32);
+ P2C(usbif_fe_interface_status_changed_t, num_ports, u32);
+ break;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED):
+ P2C(usbif_fe_driver_status_changed_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT):
+ P2C(usbif_fe_interface_connect_t, shmem_frame, memory_t);
+ break;
+ case TYPE(CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT):
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE):
+ P2C(usbif_be_create_t, domid, domid_t);
+ P2C(usbif_be_create_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY):
+ P2C(usbif_be_destroy_t, domid, domid_t);
+ P2C(usbif_be_destroy_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT):
+ P2C(usbif_be_connect_t, domid, domid_t);
+ P2C(usbif_be_connect_t, shmem_frame, memory_t);
+ P2C(usbif_be_connect_t, evtchn, u32);
+ P2C(usbif_be_connect_t, bandwidth, u32);
+ P2C(usbif_be_connect_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT):
+ P2C(usbif_be_disconnect_t, domid, domid_t);
+ P2C(usbif_be_disconnect_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_DRIVER_STATUS_CHANGED):
+ P2C(usbif_be_driver_status_changed_t, status, u32);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT):
+ P2C(usbif_be_claim_port_t, domid, domid_t);
+ P2C(usbif_be_claim_port_t, usbif_port, u32);
+ P2C(usbif_be_claim_port_t, status, u32);
+ PSTR2CHAR(usbif_be_claim_port_t, path);
+ printf("dict items parsed = %d", dict_items_parsed);
+ break;
+ case TYPE(CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT):
+ PSTR2CHAR(usbif_be_release_port_t, path);
+ break;
}
if ( dict_items_parsed != PyDict_Size(payload) )
@@ -696,43 +1043,20 @@ static PyTypeObject xu_message_type = {
* *********************** PORT ***********************
*/
-static control_if_t *map_control_interface(int fd, unsigned long pfn,
- u32 dom)
-{
- char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
- PROT_READ|PROT_WRITE, pfn );
- if ( vaddr == NULL )
- return NULL;
- return (control_if_t *)(vaddr + 2048);
-}
-static void unmap_control_interface(int fd, control_if_t *c)
-{
- char *vaddr = (char *)c - 2048;
- (void)munmap(vaddr, PAGE_SIZE);
-}
-
typedef struct xu_port_object {
PyObject_HEAD;
int xc_handle;
int connected;
u32 remote_dom;
int local_port, remote_port;
- control_if_t *interface;
- CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
- CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+ struct xu_port_object *fix_next;
} xu_port_object;
static PyObject *port_error;
+/* now a NOOP */
static PyObject *xu_port_notify(PyObject *self, PyObject *args)
{
- xu_port_object *xup = (xu_port_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
-
Py_INCREF(Py_None);
return Py_None;
}
@@ -741,39 +1065,47 @@ static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
{
xu_port_object *xup = (xu_port_object *)self;
xu_message_object *xum;
- CONTROL_RING_IDX c = xup->tx_req_cons;
- control_if_t *cif = xup->interface;
control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->tx_req_prod) ||
- ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
- {
- PyErr_SetString(port_error, "no request to read");
- return NULL;
+ unsigned i;
+ xcs_msg_ent_t *ent = NULL;
+
+ for ( i = req_cons; (i != req_prod); i++ ) {
+ ent = REQ_RING_ENT(i);
+ if (ent == NULL)
+ continue;
+ if (ent->msg.u.control.remote_dom == xup->remote_dom)
+ break;
}
+
+ if ((ent == NULL) ||
+ (ent->msg.u.control.remote_dom != xup->remote_dom))
+ goto none;
- /* Need to ensure we see the request, despite seeing the index update.*/
- rmb();
-
- cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+ cmsg = &ent->msg.u.control.msg;
xum = PyObject_New(xu_message_object, &xu_message_type);
memcpy(&xum->msg, cmsg, sizeof(*cmsg));
if ( xum->msg.length > sizeof(xum->msg.msg) )
xum->msg.length = sizeof(xum->msg.msg);
- xup->tx_req_cons++;
+ free(ent);
+
+ /* remove the entry from the ring and advance the consumer if possible */
+ REQ_RING_ENT(i) = NULL;
+ while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
+ req_cons++;
+
return (PyObject *)xum;
+
+none:
+ Py_INCREF(Py_None);
+ return Py_None;
+
}
static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
{
xu_port_object *xup = (xu_port_object *)self;
xu_message_object *xum;
- CONTROL_RING_IDX p = xup->rx_req_prod;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
+ xcs_msg_t kmsg;
if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
return NULL;
@@ -784,18 +1116,11 @@ static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
return NULL;
}
- if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
- {
- PyErr_SetString(port_error, "no space to write request");
- return NULL;
- }
-
- cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
- memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
- wmb();
- xup->rx_req_prod = cif->rx_req_prod = p + 1;
-
+ kmsg.type = XCS_REQUEST;
+ kmsg.u.control.remote_dom = xup->remote_dom;
+ memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
+ xcs_data_send(&kmsg);
+
Py_INCREF(Py_None);
return Py_None;
}
@@ -804,38 +1129,47 @@ static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
{
xu_port_object *xup = (xu_port_object *)self;
xu_message_object *xum;
- CONTROL_RING_IDX c = xup->rx_resp_cons;
- control_if_t *cif = xup->interface;
control_msg_t *cmsg;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
-
- if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
- {
- PyErr_SetString(port_error, "no response to read");
- return NULL;
+ unsigned i;
+ xcs_msg_ent_t *ent = NULL;
+
+ for ( i = rsp_cons; (i != rsp_prod); i++ ) {
+ ent = RSP_RING_ENT(i);
+ if (ent == NULL)
+ continue;
+ if (ent->msg.u.control.remote_dom == xup->remote_dom)
+ break;
}
+
+ if ((ent == NULL) ||
+ (ent->msg.u.control.remote_dom != xup->remote_dom))
+ goto none;
- /* Need to ensure we see the response, despite seeing the index update.*/
- rmb();
-
- cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+ cmsg = &ent->msg.u.control.msg;
xum = PyObject_New(xu_message_object, &xu_message_type);
memcpy(&xum->msg, cmsg, sizeof(*cmsg));
if ( xum->msg.length > sizeof(xum->msg.msg) )
xum->msg.length = sizeof(xum->msg.msg);
- xup->rx_resp_cons++;
+ free(ent);
+
+ /* remove the entry from the ring and advance the consumer if possible */
+ RSP_RING_ENT(i) = NULL;
+ while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
+ rsp_cons++;
+
return (PyObject *)xum;
+
+none:
+ Py_INCREF(Py_None);
+ return Py_None;
+
}
static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
{
xu_port_object *xup = (xu_port_object *)self;
xu_message_object *xum;
- CONTROL_RING_IDX p = xup->tx_resp_prod;
- control_if_t *cif = xup->interface;
- control_msg_t *cmsg;
+ xcs_msg_t kmsg;
if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
return NULL;
@@ -846,17 +1180,10 @@ static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
return NULL;
}
- if ( p == xup->tx_req_cons )
- {
- PyErr_SetString(port_error, "no space to write response");
- return NULL;
- }
-
- cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
- memcpy(cmsg, &xum->msg, sizeof(*cmsg));
-
- wmb();
- xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
+ kmsg.type = XCS_RESPONSE;
+ kmsg.u.control.remote_dom = xup->remote_dom;
+ memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
+ xcs_data_send(&kmsg);
Py_INCREF(Py_None);
return Py_None;
@@ -864,133 +1191,131 @@ static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX c = xup->tx_req_cons;
- control_if_t *cif = xup->interface;
-
+ xu_port_object *xup = (xu_port_object *)self;
+ xcs_msg_ent_t *ent;
+ int found = 0;
+ unsigned i;
+
if ( !PyArg_ParseTuple(args, "") )
return NULL;
- if ( (c == cif->tx_req_prod) ||
- ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
+ for ( i = req_cons; (i != req_prod); i++ ) {
+ ent = REQ_RING_ENT(i);
+ if (ent == NULL)
+ continue;
+ if (ent->msg.u.control.remote_dom == xup->remote_dom) {
+ found = 1;
+ break;
+ }
+ }
+
+ return PyInt_FromLong(found);
}
static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX p = xup->rx_req_prod;
-
if ( !PyArg_ParseTuple(args, "") )
return NULL;
- if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
- return PyInt_FromLong(0);
-
return PyInt_FromLong(1);
}
static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX c = xup->rx_resp_cons;
- control_if_t *cif = xup->interface;
-
+ xu_port_object *xup = (xu_port_object *)self;
+ xcs_msg_ent_t *ent;
+ int found = 0;
+ unsigned i;
+
if ( !PyArg_ParseTuple(args, "") )
return NULL;
- if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
- return PyInt_FromLong(0);
-
- return PyInt_FromLong(1);
+ for ( i = rsp_cons; (i != rsp_prod); i++ ) {
+ ent = RSP_RING_ENT(i);
+ if (ent == NULL)
+ continue;
+ if (ent->msg.u.control.remote_dom == xup->remote_dom) {
+ found = 1;
+ break;
+ }
+ }
+
+ return PyInt_FromLong(found);
}
static PyObject *xu_port_space_to_write_response(
PyObject *self, PyObject *args)
{
- xu_port_object *xup = (xu_port_object *)self;
- CONTROL_RING_IDX p = xup->tx_resp_prod;
-
if ( !PyArg_ParseTuple(args, "") )
return NULL;
- if ( p == xup->tx_req_cons )
- return PyInt_FromLong(0);
-
return PyInt_FromLong(1);
}
-static int __xu_port_connect(xu_port_object *xup)
+/* NOOP */
+static PyObject *xu_port_connect(PyObject *self, PyObject *args)
{
- xc_dominfo_t info;
-
- if ( xup->connected )
- {
- return 0;
- }
-
- if ( (xc_domain_getinfo(xup->xc_handle, xup->remote_dom, 1, &info) != 1) ||
- (info.domid != xup->remote_dom) )
- {
- PyErr_SetString(port_error, "Failed to obtain domain status");
- return -1;
- }
-
- xup->interface =
- map_control_interface(xup->xc_handle, info.shared_info_frame,
- xup->remote_dom);
-
- if ( xup->interface == NULL )
- {
- PyErr_SetString(port_error, "Failed to map domain control interface");
- return -1;
- }
-
- /* Synchronise ring indexes. */
- xup->tx_resp_prod = xup->interface->tx_resp_prod;
- xup->tx_req_cons = xup->interface->tx_resp_prod;
- xup->rx_req_prod = xup->interface->rx_req_prod;
- xup->rx_resp_cons = xup->interface->rx_resp_prod;
-
- xup->connected = 1;
-
- return 0;
+ Py_INCREF(Py_None);
+ return Py_None;
}
-static void __xu_port_disconnect(xu_port_object *xup)
+/* NOOP */
+static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
{
- if ( xup->connected )
- unmap_control_interface(xup->xc_handle, xup->interface);
- xup->connected = 0;
+ Py_INCREF(Py_None);
+ return Py_None;
}
-static PyObject *xu_port_connect(PyObject *self, PyObject *args)
+static PyObject *xu_port_register(PyObject *self, PyObject *args,
+ PyObject *kwds)
{
- xu_port_object *xup = (xu_port_object *)self;
-
- if ( !PyArg_ParseTuple(args, "") )
- return NULL;
+ int type;
+ xcs_msg_t msg;
+ xu_port_object *xup = (xu_port_object *)self;
+ static char *kwd_list[] = { "type", NULL };
- if ( __xu_port_connect(xup) != 0 )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
+ &type) )
return NULL;
-
- Py_INCREF(Py_None);
- return Py_None;
+
+ msg.type = XCS_MSG_BIND;
+ msg.u.bind.port = xup->local_port;
+ msg.u.bind.type = type;
+ xcs_ctrl_send(&msg);
+ xcs_ctrl_read(&msg);
+
+ if (msg.result != XCS_RSLT_OK)
+ {
+ return PyInt_FromLong(0);
+ }
+
+ return PyInt_FromLong(1);
}
-static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
+static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
+ PyObject *kwds)
{
- xu_port_object *xup = (xu_port_object *)self;
+ int type;
+ xcs_msg_t msg;
+ xu_port_object *xup = (xu_port_object *)self;
+ static char *kwd_list[] = { "type", NULL };
- if ( !PyArg_ParseTuple(args, "") )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
+ &type) )
return NULL;
-
- __xu_port_disconnect(xup);
-
- Py_INCREF(Py_None);
- return Py_None;
+
+ msg.type = XCS_MSG_UNBIND;
+ msg.u.bind.port = xup->local_port;
+ msg.u.bind.type = type;
+ xcs_ctrl_send(&msg);
+ xcs_ctrl_read(&msg);
+
+ if (msg.result != XCS_RSLT_OK)
+ {
+ return PyInt_FromLong(0);
+ }
+
+ return PyInt_FromLong(1);
}
static PyMethodDef xu_port_methods[] = {
@@ -1038,6 +1363,16 @@ static PyMethodDef xu_port_methods[] = {
(PyCFunction)xu_port_space_to_write_response,
METH_VARARGS,
"Returns TRUE if there is space to write a response message.\n" },
+
+ { "register",
+ (PyCFunction)xu_port_register,
+ METH_VARARGS | METH_KEYWORDS,
+ "Register to receive a type of message on this channel.\n" },
+
+ { "deregister",
+ (PyCFunction)xu_port_deregister,
+ METH_VARARGS | METH_KEYWORDS,
+ "Stop receiving a type of message on this port.\n" },
{ "connect",
(PyCFunction)xu_port_connect,
@@ -1059,6 +1394,7 @@ static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
xu_port_object *xup;
u32 dom;
int port1 = 0, port2 = 0;
+ xcs_msg_t kmsg;
static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
@@ -1070,51 +1406,26 @@ static PyObject *xu_port_new(PyObject *self, PyObject *args, PyObject *kwds)
xup->connected = 0;
xup->remote_dom = dom;
-
- if ( (xup->xc_handle = xc_interface_open()) == -1 )
- {
- PyErr_SetString(port_error, "Could not open Xen control interface");
+
+ kmsg.type = XCS_CIF_NEW_CC;
+ kmsg.u.interface.dom = xup->remote_dom;
+ kmsg.u.interface.local_port = port1;
+ kmsg.u.interface.remote_port = port2;
+ xcs_ctrl_send(&kmsg);
+ xcs_ctrl_read(&kmsg);
+
+ if ( kmsg.result != XCS_RSLT_OK )
goto fail1;
- }
-
- if ( dom == 0 )
- {
- /*
- * The control-interface event channel for DOM0 is already set up.
- * We use an ioctl to discover the port at our end of the channel.
- */
- port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
- port2 = -1; /* We don't need the remote end of the DOM0 link. */
- if ( port1 < 0 )
- {
- PyErr_SetString(port_error, "Could not open channel to DOM0");
- goto fail2;
- }
- }
- else if ( xc_evtchn_bind_interdomain(xup->xc_handle,
- DOMID_SELF, dom,
- &port1, &port2) != 0 )
- {
- PyErr_SetString(port_error, "Could not open channel to domain");
- goto fail2;
- }
-
- xup->local_port = port1;
- xup->remote_port = port2;
-
- if ( __xu_port_connect(xup) != 0 )
- goto fail3;
-
+
+ xup->local_port = kmsg.u.interface.local_port;
+ xup->remote_port = kmsg.u.interface.remote_port;
+ xup->connected = 1;
+
return (PyObject *)xup;
-
- fail3:
- if ( dom != 0 )
- (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
- fail2:
- (void)xc_interface_close(xup->xc_handle);
+
fail1:
PyObject_Del((PyObject *)xup);
- return NULL;
+ return NULL;
}
static PyObject *xu_port_getattr(PyObject *obj, char *name)
@@ -1131,11 +1442,20 @@ static PyObject *xu_port_getattr(PyObject *obj, char *name)
static void xu_port_dealloc(PyObject *self)
{
+
xu_port_object *xup = (xu_port_object *)self;
- __xu_port_disconnect(xup);
+ xcs_msg_t kmsg;
+
if ( xup->remote_dom != 0 )
- (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
- (void)xc_interface_close(xup->xc_handle);
+ {
+ kmsg.type = XCS_CIF_FREE_CC;
+ kmsg.u.interface.dom = xup->remote_dom;
+ kmsg.u.interface.local_port = xup->local_port;
+ kmsg.u.interface.remote_port = xup->remote_port;
+ xcs_ctrl_send(&kmsg);
+ xcs_ctrl_read(&kmsg);
+ }
+
PyObject_Del(self);
}
diff --git a/tools/python/xen/util/memmap.py b/tools/python/xen/util/memmap.py
new file mode 100644
index 0000000000..2899a87535
--- /dev/null
+++ b/tools/python/xen/util/memmap.py
@@ -0,0 +1,41 @@
+mem_caching_attr = {
+ 'UC' : 0,
+ 'WC' : 1,
+ 'WT' : 4,
+ 'WP' : 5,
+ 'WB' : 6,
+ };
+
+e820_mem_type = {
+ 'AddressRangeMemory' : 1,
+ 'AddressRangeReserved' : 2,
+ 'AddressRangeACPI' : 3,
+ 'AddressRangeNVS' : 4,
+ 'AddressRangeIO' : 16,
+ 'AddressRangeShared' : 17,
+};
+
+MT_COL = 2
+MA_COL = 3
+
+def strmap(row):
+ if (type(row) != type([])):
+ return row
+ row[MT_COL] = e820_mem_type[row[MT_COL]]
+ row[MA_COL] = mem_caching_attr[row[MA_COL]]
+ return row
+
+def memmap_parse(memmap):
+ return map(strmap, memmap)
+
+if __name__ == '__main__':
+ memmap = [ 'memmap',
+ [ '1', '2', 'AddressRangeMemory', 'UC'],
+ [ '1', '2', 'AddressRangeReserved', 'UC'],
+ [ '1', '2', 'AddressRangeACPI', 'WB'],
+ [ '1', '2', 'AddressRangeNVS', 'WB'],
+ [ '1', '2', 'AddressRangeIO', 'WB'],
+ [ '1', '2', 'AddressRangeShared', 'WB']]
+ print memmap_parse(memmap);
+
+
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 05647c83ab..22a0a8b282 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -20,6 +20,7 @@ from twisted.internet import defer
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
import xen.util.ip
from xen.util.ip import _readline, _readlines
+from xen.xend.server import channel
import sxp
@@ -319,6 +320,9 @@ class XendDomainInfo:
self.restart_time = None
self.console_port = None
self.savedinfo = None
+ self.image_handler = None
+ self.is_vmx = 0
+ self.vcpus = 1
def setdom(self, dom):
"""Set the domain id.
@@ -446,7 +450,13 @@ class XendDomainInfo:
cpu = sxp.child_value(config, 'cpu')
if self.recreate and self.dom and cpu is not None:
xc.domain_pincpu(self.dom, int(cpu))
+ try:
+ image = sxp.child_value(self.config, 'image')
+ self.vcpus = int(sxp.child_value(image, 'vcpus'))
+ except:
+ raise VmError('invalid vcpus value')
+ self.find_image_handler()
self.init_domain()
self.configure_console()
self.configure_backends()
@@ -463,7 +473,7 @@ class XendDomainInfo:
raise
return deferred
- def construct_image(self):
+ def find_image_handler(self):
"""Construct the boot image for the domain.
@return vm
@@ -474,10 +484,17 @@ class XendDomainInfo:
image_name = sxp.name(image)
if image_name is None:
raise VmError('missing image name')
+ if image_name == "vmx":
+ self.is_vmx = 1
image_handler = get_image_handler(image_name)
if image_handler is None:
raise VmError('unknown image type: ' + image_name)
- image_handler(self, image)
+ self.image_handler = image_handler
+ return self
+
+ def construct_image(self):
+ image = sxp.child_value(self.config, 'image')
+ self.image_handler(self, image)
return self
def config_devices(self, name):
@@ -650,6 +667,7 @@ class XendDomainInfo:
"""
self.release_vifs()
self.release_vbds()
+ self.release_usbifs()
self.devices = {}
self.device_index = {}
@@ -674,6 +692,15 @@ class XendDomainInfo:
log.debug("Destroying vbds for domain %d", self.dom)
ctrl.destroy()
+ def release_usbifs(self):
+ """Release vm virtual USB devices (usbifs).
+ """
+ if self.dom is None: return
+ ctrl = xend.usbif_get(self.dom)
+ if ctrl:
+ log.debug("Destroying usbifs for domain %d", self.dom)
+ ctrl.destroy()
+
def show(self):
"""Print virtual machine info.
"""
@@ -712,7 +739,8 @@ class XendDomainInfo:
except:
raise VmError('invalid cpu')
cpu_weight = self.cpu_weight
- dom = xc.domain_create(dom= dom, mem_kb= memory * 1024,
+ memory = memory * 1024 + self.pgtable_size(memory)
+ dom = xc.domain_create(dom= dom, mem_kb= memory,
cpu= cpu, cpu_weight= cpu_weight)
if dom <= 0:
raise VmError('Creating domain failed: name=%s memory=%d'
@@ -720,7 +748,7 @@ class XendDomainInfo:
log.debug('init_domain> Created domain=%d name=%s memory=%d', dom, name, memory)
self.setdom(dom)
- def build_domain(self, ostype, kernel, ramdisk, cmdline):
+ def build_domain(self, ostype, kernel, ramdisk, cmdline, memmap):
"""Build the domain boot image.
"""
if self.recreate or self.restore: return
@@ -735,17 +763,29 @@ class XendDomainInfo:
flags = 0
if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
- err = buildfn(dom = dom,
- image = kernel,
- control_evtchn = self.console.getRemotePort(),
- cmdline = cmdline,
- ramdisk = ramdisk,
- flags = flags)
+ if ostype == "vmx":
+ err = buildfn(dom = dom,
+ image = kernel,
+ control_evtchn = 0,
+ memsize = self.memory,
+ memmap = memmap,
+ cmdline = cmdline,
+ ramdisk = ramdisk,
+ flags = flags)
+ else:
+ log.warning('building dom with %d vcpus', self.vcpus)
+ err = buildfn(dom = dom,
+ image = kernel,
+ control_evtchn = self.console.getRemotePort(),
+ cmdline = cmdline,
+ ramdisk = ramdisk,
+ flags = flags,
+ vcpus = self.vcpus)
if err != 0:
raise VmError('Building domain failed: type=%s dom=%d err=%d'
% (ostype, dom, err))
- def create_domain(self, ostype, kernel, ramdisk, cmdline):
+ def create_domain(self, ostype, kernel, ramdisk, cmdline, memmap=''):
"""Create a domain. Builds the image but does not configure it.
@param ostype: OS type
@@ -760,7 +800,7 @@ class XendDomainInfo:
else:
self.console = xendConsole.console_create(
self.dom, console_port=self.console_port)
- self.build_domain(ostype, kernel, ramdisk, cmdline)
+ self.build_domain(ostype, kernel, ramdisk, cmdline, memmap)
self.image = kernel
self.ramdisk = ramdisk
self.cmdline = cmdline
@@ -804,6 +844,18 @@ class XendDomainInfo:
index[dev_name] = dev_index + 1
deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
deferred.addErrback(dlist_err)
+ if self.is_vmx:
+ device_model = sxp.child_value(self.config, 'device_model')
+ device_config = sxp.child_value(self.config, 'device_config')
+ memory = sxp.child_value(self.config, "memory")
+ # Create an event channel
+ device_channel = channel.eventChannel(0, self.dom)
+ # Fork and exec device_model -f device_config <port>
+ os.system(device_model
+ + " -f %s" % device_config
+ + " -d %d" % self.dom
+ + " -p %d" % device_channel['port1']
+ + " -m %s &" % memory)
return deferred
def device_create(self, dev_config):
@@ -963,6 +1015,8 @@ class XendDomainInfo:
self.blkif_backend = 1
elif name == 'netif':
self.netif_backend = 1
+ elif name == 'usbif':
+ self.usbif_backend = 1
else:
raise VmError('invalid backend type:' + str(name))
@@ -1041,6 +1095,18 @@ class XendDomainInfo:
d.addErrback(dlist_err)
return d
+ def pgtable_size(self, memory):
+ """Return the size of memory needed for 1:1 page tables for physical
+ mode.
+
+ @param memory: size in MB
+ @return size in KB
+ """
+ if self.is_vmx:
+ # Logic x86-32 specific.
+ # 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
+ return (1 + ((memory + 3) >> 2)) * 4
+ return 0
def vm_image_linux(vm, image):
"""Create a VM for a linux image.
@@ -1091,7 +1157,32 @@ def vm_image_plan9(vm, image):
vm.create_domain("plan9", kernel, ramdisk, cmdline)
return vm
-
+def vm_image_vmx(vm, image):
+ """Create a VM for the VMX environment.
+
+ @param name: vm name
+ @param memory: vm memory
+ @param image: image config
+ @return: vm
+ """
+ kernel = sxp.child_value(image, "kernel")
+ cmdline = ""
+ ip = sxp.child_value(image, "ip", "dhcp")
+ if ip:
+ cmdline += " ip=" + ip
+ root = sxp.child_value(image, "root")
+ if root:
+ cmdline += " root=" + root
+ args = sxp.child_value(image, "args")
+ if args:
+ cmdline += " " + args
+ ramdisk = sxp.child_value(image, "ramdisk", '')
+ memmap = sxp.child_value(vm.config, "memmap", '')
+ memmap = sxp.parse(open(memmap))[0]
+ from xen.util.memmap import memmap_parse
+ memmap = memmap_parse(memmap)
+ vm.create_domain("vmx", kernel, ramdisk, cmdline, memmap)
+ return vm
def vm_dev_vif(vm, val, index, change=0):
"""Create a virtual network interface (vif).
@@ -1117,6 +1208,23 @@ def vm_dev_vif(vm, val, index, change=0):
defer.addCallback(cbok)
return defer
+def vm_dev_usb(vm, val, index):
+ """Attach the relevant physical ports to the domains' USB interface.
+
+ @param vm: virtual machine
+ @param val: USB interface config
+ @param index: USB interface index
+ @return: deferred
+ """
+ ctrl = xend.usbif_create(vm.dom, recreate=vm.recreate)
+ log.debug("Creating USB interface dom=%d", vm.dom)
+ defer = ctrl.attachDevice(val, recreate=vm.recreate)
+ def cbok(path):
+ vm.add_device('usb', val[1][1])
+ return path
+ defer.addCallback(cbok)
+ return defer
+
def vm_dev_vbd(vm, val, index, change=0):
"""Create a virtual block device (vbd).
@@ -1215,11 +1323,13 @@ def vm_field_maxmem(vm, config, val, index):
# Register image handlers.
add_image_handler('linux', vm_image_linux)
add_image_handler('plan9', vm_image_plan9)
+add_image_handler('vmx', vm_image_vmx)
# Register device handlers.
add_device_handler('vif', vm_dev_vif)
add_device_handler('vbd', vm_dev_vbd)
add_device_handler('pci', vm_dev_pci)
+add_device_handler('usb', vm_dev_usb)
# Ignore the fields we already handle.
add_config_handler('name', vm_field_ignore)
@@ -1230,6 +1340,7 @@ add_config_handler('console', vm_field_ignore)
add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
add_config_handler('backend', vm_field_ignore)
+add_config_handler('vcpus', vm_field_ignore)
# Register other config handlers.
add_config_handler('maxmem', vm_field_maxmem)
diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py
index 338d6e4d4a..860848ace7 100644
--- a/tools/python/xen/xend/server/SrvDaemon.py
+++ b/tools/python/xen/xend/server/SrvDaemon.py
@@ -40,6 +40,7 @@ from xen.util.ip import _readline, _readlines
import channel
import blkif
import netif
+import usbif
import console
import domain
from params import *
@@ -118,9 +119,9 @@ class NotifierPort(abstract.FileDescriptor):
if hasattr(self, 'protocol'):
self.protocol.doStop()
self.connected = 0
- #self.notifier.close() # Not implemented.
- os.close(self.fileno())
- del self.notifier
+ #self.notifier.close() # (this said:) Not implemented.
+ #os.close(self.fileno()) # But yes it is...
+ del self.notifier # ...as _dealloc!
if hasattr(self, 'd'):
self.d.callback(None)
del self.d
@@ -261,6 +262,7 @@ class EventProtocol(protocol.Protocol):
val += self.daemon.consoles()
val += self.daemon.blkifs()
val += self.daemon.netifs()
+ val += self.daemon.usbifs()
return val
def op_sys_subscribe(self, name, v):
@@ -617,6 +619,7 @@ class Daemon:
self.domainCF = domain.DomainControllerFactory()
self.blkifCF = blkif.BlkifControllerFactory()
self.netifCF = netif.NetifControllerFactory()
+ self.usbifCF = usbif.UsbifControllerFactory()
self.consoleCF = console.ConsoleControllerFactory()
def listenEvent(self):
@@ -683,6 +686,15 @@ class Daemon:
def netif_get(self, dom):
return self.netifCF.getControllerByDom(dom)
+ def usbif_create(self, dom, recreate=0):
+ return self.usbifCF.getController(dom)
+
+ def usbifs(self):
+ return [ x.sxpr() for x in self.usbifCF.getControllers() ]
+
+ def usbif_get(self, dom):
+ return self.usbifCF.getControllerByDom(dom)
+
def console_create(self, dom, console_port=None):
"""Create a console for a domain.
"""
diff --git a/tools/python/xen/xend/server/SrvUsbif.py b/tools/python/xen/xend/server/SrvUsbif.py
new file mode 100644
index 0000000000..bdd57524ce
--- /dev/null
+++ b/tools/python/xen/xend/server/SrvUsbif.py
@@ -0,0 +1,249 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from twisted.protocols import http
+
+from xen.xend import sxp
+from xen.xend import XendDomain
+from xen.xend import XendConsole
+from xen.xend import PrettyPrint
+from xen.xend.Args import FormFn
+
+from SrvDir import SrvDir
+
+class SrvDomain(SrvDir):
+ """Service managing a single domain.
+ """
+
+ def __init__(self, dom):
+ SrvDir.__init__(self)
+ self.dom = dom
+ self.xd = XendDomain.instance()
+ self.xconsole = XendConsole.instance()
+
+ def op_configure(self, op, req):
+ """Configure an existing domain.
+ Configure is unusual in that it requires a domain id,
+ not a domain name.
+ """
+ fn = FormFn(self.xd.domain_configure,
+ [['dom', 'int'],
+ ['config', 'sxpr']])
+ deferred = fn(req.args, {'dom': self.dom.dom})
+ deferred.addErrback(self._op_configure_err, req)
+ return deferred
+
+ def _op_configure_err(self, err, req):
+ req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
+ return str(err)
+
+ def op_unpause(self, op, req):
+ val = self.xd.domain_unpause(self.dom.name)
+ return val
+
+ def op_pause(self, op, req):
+ val = self.xd.domain_pause(self.dom.name)
+ return val
+
+ def op_shutdown(self, op, req):
+ fn = FormFn(self.xd.domain_shutdown,
+ [['dom', 'str'],
+ ['reason', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ req.setResponseCode(http.ACCEPTED)
+ req.setHeader("Location", "%s/.." % req.prePathURL())
+ return val
+
+ def op_destroy(self, op, req):
+ fn = FormFn(self.xd.domain_destroy,
+ [['dom', 'str'],
+ ['reason', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ req.setHeader("Location", "%s/.." % req.prePathURL())
+ return val
+
+ def op_save(self, op, req):
+ fn = FormFn(self.xd.domain_save,
+ [['dom', 'str'],
+ ['file', 'str']])
+ deferred = fn(req.args, {'dom': self.dom.id})
+ deferred.addCallback(self._op_save_cb, req)
+ deferred.addErrback(self._op_save_err, req)
+ return deferred
+
+ def _op_save_cb(self, val, req):
+ return 0
+
+ def _op_save_err(self, err, req):
+ req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
+ return str(err)
+
+ def op_migrate(self, op, req):
+ fn = FormFn(self.xd.domain_migrate,
+ [['dom', 'str'],
+ ['destination', 'str'],
+ ['live', 'int']])
+ deferred = fn(req.args, {'dom': self.dom.id})
+ print 'op_migrate>', deferred
+ deferred.addCallback(self._op_migrate_cb, req)
+ deferred.addErrback(self._op_migrate_err, req)
+ return deferred
+
+ def _op_migrate_cb(self, info, req):
+ print '_op_migrate_cb>', info, req
+ #req.setResponseCode(http.ACCEPTED)
+ host = info.dst_host
+ port = info.dst_port
+ dom = info.dst_dom
+ url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
+ req.setHeader("Location", url)
+ print '_op_migrate_cb> url=', url
+ return url
+
+ def _op_migrate_err(self, err, req):
+ print '_op_migrate_err>', err, req
+ req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
+ return str(err)
+
+ def op_pincpu(self, op, req):
+ fn = FormFn(self.xd.domain_pincpu,
+ [['dom', 'str'],
+ ['cpu', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_cpu_bvt_set(self, op, req):
+ fn = FormFn(self.xd.domain_cpu_bvt_set,
+ [['dom', 'str'],
+ ['mcuadv', 'int'],
+ ['warpback', 'int'],
+ ['warpvalue', 'int'],
+ ['warpl', 'long'],
+ ['warpu', 'long']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_cpu_fbvt_set(self, op, req):
+ fn = FormFn(self.xd.domain_cpu_fbvt_set,
+ [['dom', 'str'],
+ ['mcuadv', 'int'],
+ ['warp', 'int'],
+ ['warpl', 'int'],
+ ['warpu', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_cpu_atropos_set(self, op, req):
+ fn = FormFn(self.xd.domain_cpu_atropos_set,
+ [['dom', 'str'],
+ ['period', 'int'],
+ ['slice', 'int'],
+ ['latency', 'int'],
+ ['xtratime', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_maxmem_set(self, op, req):
+ fn = FormFn(self.xd.domain_maxmem_set,
+ [['dom', 'str'],
+ ['memory', 'int']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_device_create(self, op, req):
+ fn = FormFn(self.xd.domain_device_create,
+ [['dom', 'str'],
+ ['config', 'sxpr']])
+ d = fn(req.args, {'dom': self.dom.id})
+ return d
+
+ def op_device_destroy(self, op, req):
+ fn = FormFn(self.xd.domain_device_destroy,
+ [['dom', 'str'],
+ ['type', 'str'],
+ ['idx', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_vifs(self, op, req):
+ devs = self.xd.domain_vif_ls(self.dom.id)
+ return [ dev.sxpr() for dev in devs ]
+
+ def op_vif(self, op, req):
+ fn = FormFn(self.xd.domain_vif_get,
+ [['dom', 'str'],
+ ['vif', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def op_vbds(self, op, req):
+ devs = self.xd.domain_vbd_ls(self.dom.id)
+ return [ dev.sxpr() for dev in devs ]
+
+ def op_vbd(self, op, req):
+ fn = FormFn(self.xd.domain_vbd_get,
+ [['dom', 'str'],
+ ['vbd', 'str']])
+ val = fn(req.args, {'dom': self.dom.id})
+ return val
+
+ def render_POST(self, req):
+ return self.perform(req)
+
+ def render_GET(self, req):
+ op = req.args.get('op')
+ if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd']:
+ return self.perform(req)
+ if self.use_sxp(req):
+ req.setHeader("Content-Type", sxp.mime_type)
+ sxp.show(self.dom.sxpr(), out=req)
+ else:
+ req.write('<html><head></head><body>')
+ self.print_path(req)
+ #self.ls()
+ req.write('<p>%s</p>' % self.dom)
+ if self.dom.console:
+ cinfo = self.dom.console
+ cid = str(cinfo.console_port)
+ #todo: Local xref: need to know server prefix.
+ req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
+ % (cid, cid))
+ req.write('<p><a href="%s">Connect to console</a></p>'
+ % cinfo.uri())
+ if self.dom.config:
+ req.write("<code><pre>")
+ PrettyPrint.prettyprint(self.dom.config, out=req)
+ req.write("</pre></code>")
+ self.form(req)
+ req.write('</body></html>')
+ return ''
+
+ def form(self, req):
+ url = req.prePathURL()
+ req.write('<form method="post" action="%s">' % url)
+ req.write('<input type="submit" name="op" value="unpause">')
+ req.write('<input type="submit" name="op" value="pause">')
+ req.write('</form>')
+
+ req.write('<form method="post" action="%s">' % url)
+ req.write('<input type="submit" name="op" value="destroy">')
+ req.write('<input type="radio" name="reason" value="halt" checked>Halt')
+ req.write('<input type="radio" name="reason" value="reboot">Reboot')
+ req.write('</form>')
+
+ req.write('<form method="post" action="%s">' % url)
+ req.write('<input type="submit" name="op" value="shutdown">')
+ req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
+ req.write('<input type="radio" name="reason" value="halt">Halt')
+ req.write('<input type="radio" name="reason" value="reboot">Reboot')
+ req.write('</form>')
+
+ req.write('<form method="post" action="%s">' % url)
+ req.write('<br><input type="submit" name="op" value="save">')
+ req.write(' To file: <input type="text" name="file">')
+ req.write('</form>')
+
+ req.write('<form method="post" action="%s">' % url)
+ req.write('<br><input type="submit" name="op" value="migrate">')
+ req.write(' To host: <input type="text" name="destination">')
+ req.write('<input type="checkbox" name="live" value="1">Live')
+ req.write('</form>')
diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py
index 127f38f2c0..6dfebe37be 100755
--- a/tools/python/xen/xend/server/channel.py
+++ b/tools/python/xen/xend/server/channel.py
@@ -171,8 +171,10 @@ class VirqChannel(BaseChannel):
"""
BaseChannel.__init__(self, factory)
self.virq = virq
+ self.factory = factory
# Notification port (int).
- self.port = xc.evtchn_bind_virq(virq)
+ #self.port = xc.evtchn_bind_virq(virq)
+ self.port = factory.notifier.bind_virq(virq)
self.idx = self.port
# Clients to call when a virq arrives.
self.clients = []
@@ -208,7 +210,8 @@ class VirqChannel(BaseChannel):
c.virqReceived(self.virq)
def notify(self):
- xc.evtchn_send(self.port)
+ # xc.evtchn_send(self.port)
+ self.factory.notifier.virq_send(self.port)
class Channel(BaseChannel):
@@ -279,6 +282,7 @@ class Channel(BaseChannel):
self.devs.append(dev)
for ty in types:
self.devs_by_type[ty] = dev
+ self.port.register(ty)
def deregisterDevice(self, dev):
"""Remove the registration for a device controller.
@@ -290,6 +294,7 @@ class Channel(BaseChannel):
types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
for ty in types:
del self.devs_by_type[ty]
+ self.port.deregister(ty)
def getDevice(self, type):
"""Get the device controller handling a message type.
diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py
index 35f9db986e..4f9f9119a2 100644
--- a/tools/python/xen/xend/server/messages.py
+++ b/tools/python/xen/xend/server/messages.py
@@ -189,6 +189,70 @@ netif_formats = {
msg_formats.update(netif_formats)
#============================================================================
+# USB interface message types.
+#============================================================================
+
+CMSG_USBIF_BE = 8
+CMSG_USBIF_FE = 9
+
+CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED = 0
+
+CMSG_USBIF_FE_DRIVER_STATUS_CHANGED = 32
+CMSG_USBIF_FE_INTERFACE_CONNECT = 33
+CMSG_USBIF_FE_INTERFACE_DISCONNECT = 34
+
+USBIF_DRIVER_STATUS_DOWN = 0
+USBIF_DRIVER_STATUS_UP = 1
+
+USBIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
+USBIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
+USBIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
+
+CMSG_USBIF_BE_CREATE = 0
+CMSG_USBIF_BE_DESTROY = 1
+CMSG_USBIF_BE_CONNECT = 2
+
+CMSG_USBIF_BE_DISCONNECT = 3
+CMSG_USBIF_BE_CLAIM_PORT = 4
+CMSG_USBIF_BE_RELEASE_PORT = 5
+
+CMSG_USBIF_BE_DRIVER_STATUS_CHANGED = 32
+
+USBIF_BE_STATUS_OKAY = 0
+USBIF_BE_STATUS_ERROR = 1
+
+USBIF_BE_STATUS_INTERFACE_EXISTS = 2
+USBIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
+USBIF_BE_STATUS_INTERFACE_CONNECTED = 4
+USBIF_BE_STATUS_OUT_OF_MEMORY = 7
+USBIF_BE_STATUS_MAPPING_ERROR = 9
+
+usbif_formats = {
+ 'usbif_be_create_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_CREATE),
+ 'usbif_be_destroy_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_DESTROY),
+ 'usbif_be_connect_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_CONNECT),
+ 'usbif_be_disconnect_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_DISCONNECT),
+ 'usbif_be_claim_port_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_CLAIM_PORT),
+ 'usbif_be_release_port_t':
+ (CMSG_USBIF_BE, CMSG_USBIF_BE_RELEASE_PORT),
+ 'usbif_fe_interface_status_changed_t':
+ (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED),
+ 'usbif_fe_driver_status_changed_t':
+ (CMSG_USBIF_FE, CMSG_USBIF_FE_DRIVER_STATUS_CHANGED),
+ 'usbif_fe_interface_connect_t':
+ (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_CONNECT),
+ 'usbif_fe_interface_disconnect_t':
+ (CMSG_USBIF_FE, CMSG_USBIF_FE_INTERFACE_DISCONNECT)
+ }
+
+msg_formats.update(usbif_formats)
+
+#============================================================================
# Domain shutdown message types.
#============================================================================
@@ -266,9 +330,9 @@ def packMsg(ty, params):
(major, minor) = msg_formats[ty]
args = {}
for (k, v) in params.items():
- if k == 'mac':
+ if k in ['mac', 'be_mac']:
for i in range(0, 6):
- args['mac[%d]' % i] = v[i]
+ args['%s[%d]' % (k, i)] = v[i]
else:
args[k] = v
msg = xu.message(major, minor, msgid, args)
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index d63c342435..00ad1f138b 100755
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -109,7 +109,14 @@ class NetDev(controller.SplitDev):
vmac = sxp.child_value(config, 'mac')
if not vmac: return None
mac = [ int(x, 16) for x in vmac.split(':') ]
- if len(mac) != 6: raise XendError("invalid mac")
+ if len(mac) != 6: raise XendError("invalid mac: %s" % vmac)
+ return mac
+
+ def _get_config_be_mac(self, config):
+ vmac = sxp.child_value(config, 'be_mac')
+ if not vmac: return None
+ mac = [ int(x, 16) for x in vmac.split(':') ]
+ if len(mac) != 6: raise XendError("invalid backend mac: %s" % vmac)
return mac
def _get_config_ipaddr(self, config):
@@ -127,6 +134,7 @@ class NetDev(controller.SplitDev):
return self.reconfigure(config)
self.config = config
self.mac = None
+ self.be_mac = None
self.bridge = None
self.script = None
self.ipaddr = []
@@ -135,6 +143,7 @@ class NetDev(controller.SplitDev):
if mac is None:
raise XendError("invalid mac")
self.mac = mac
+ self.be_mac = self._get_config_be_mac(config)
self.bridge = sxp.child_value(config, 'bridge')
self.script = sxp.child_value(config, 'script')
self.ipaddr = self._get_config_ipaddr(config) or []
@@ -159,6 +168,7 @@ class NetDev(controller.SplitDev):
"""
changes = {}
mac = self._get_config_mac(config)
+ be_mac = self._get_config_be_mac(config)
bridge = sxp.child_value(config, 'bridge')
script = sxp.child_value(config, 'script')
ipaddr = self._get_config_ipaddr(config)
@@ -166,6 +176,8 @@ class NetDev(controller.SplitDev):
backendDomain = str(xd.domain_lookup(sxp.child_value(config, 'backend', '0')).id)
if (mac is not None) and (mac != self.mac):
raise XendError("cannot change mac")
+ if (be_mac is not None) and (be_mac != self.be_mac):
+ raise XendError("cannot change backend mac")
if (backendDomain is not None) and (backendDomain != str(self.backendDomain)):
raise XendError("cannot change backend")
if (bridge is not None) and (bridge != self.bridge):
@@ -190,6 +202,8 @@ class NetDev(controller.SplitDev):
['idx', self.idx],
['vif', vif],
['mac', mac]]
+ if self.be_mac:
+ val.append(['be_mac', self.get_be_mac()])
if self.bridge:
val.append(['bridge', self.bridge])
if self.script:
@@ -214,6 +228,11 @@ class NetDev(controller.SplitDev):
"""
return ':'.join(map(lambda x: "%02x" % x, self.mac))
+ def get_be_mac(self):
+ """Get the backend MAC address as a string.
+ """
+ return ':'.join(map(lambda x: "%02x" % x, self.be_mac))
+
def vifctl_params(self, vmname=None):
"""Get the parameters to pass to vifctl.
"""
@@ -267,6 +286,7 @@ class NetDev(controller.SplitDev):
msg = packMsg('netif_be_create_t',
{ 'domid' : self.controller.dom,
'netif_handle' : self.vif,
+ 'be_mac' : self.be_mac or [0, 0, 0, 0, 0, 0],
'mac' : self.mac })
self.getBackendInterface().writeRequest(msg, response=d)
return d
diff --git a/tools/python/xen/xend/server/usbif.py b/tools/python/xen/xend/server/usbif.py
new file mode 100644
index 0000000000..d90997634b
--- /dev/null
+++ b/tools/python/xen/xend/server/usbif.py
@@ -0,0 +1,368 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+# Copyright (C) 2004 Intel Research Cambridge
+# Copyright (C) 2004 Mark Williamson <mark.williamson@cl.cam.ac.uk>
+"""Support for virtual USB hubs.
+"""
+
+from twisted.internet import defer
+#defer.Deferred.debug = 1
+
+from xen.xend import sxp
+from xen.xend.XendLogging import log
+from xen.xend.XendError import XendError
+
+import channel
+import controller
+from messages import *
+
+class UsbifBackendController(controller.BackendController):
+ """ Handler for the 'back-end' channel to a USB hub domain.
+ Must be connected using connect() before it can be used.
+ Do not create directly - use getBackend() on the UsbifController.
+ """
+
+ def __init__(self, ctrl, dom):
+ controller.BackendController.__init__(self, ctrl, dom)
+ self.connected = 0
+ self.evtchn = None
+ self.addMethod(CMSG_USBIF_BE,
+ CMSG_USBIF_BE_DRIVER_STATUS_CHANGED,
+ self.recv_be_driver_status_changed)
+ self.registerChannel()
+
+ def __str__(self):
+ return '<UsbifBackendController %d>' % (self.dom)
+
+ def recv_be_driver_status_changed(self, msg, req):
+ """Request handler for be_driver_status_changed messages.
+
+ @param msg: message
+ @type msg: xu message
+ @param req: request flag (true if the msg is a request)
+ @type req: bool
+ """
+ val = unpackMsg('usbif_be_driver_status_changed_t', msg)
+ status = val['status']
+
+class UsbifBackendInterface(controller.BackendInterface):
+ """Handler for the 'back-end' channel to a network device driver domain
+ on behalf of a front-end domain.
+
+ Each network device is handled separately, so we add no functionality
+ here.
+ """
+ def __init__(self, ctrl, dom):
+ controller.BackendInterface.__init__(self, ctrl, dom, 0)
+ self.connected = 0
+ self.connecting = False
+
+ def connect(self, recreate=0):
+ """Connect the controller to the usbif control interface.
+
+ @param recreate: true if after xend restart
+ @return: deferred
+ """
+ log.debug("Connecting usbif %s", str(self))
+ if recreate or self.connected or self.connecting:
+ d = defer.succeed(self)
+ else:
+ self.connecting = True
+ d = self.send_be_create()
+ d.addCallback(self.respond_be_create)
+ return d
+
+ def send_be_create(self):
+ d = defer.Deferred()
+ msg = packMsg('usbif_be_create_t',
+ { 'domid' : self.controller.dom })
+ self.writeRequest(msg, response=d)
+ return d
+
+ def respond_be_create(self, msg):
+ val = unpackMsg('usbif_be_create_t', msg)
+ log.debug('>UsbifBackendController>respond_be_create> %s', str(val))
+ self.connected = True
+ return self
+
+ def destroy(self):
+ """Disconnect from the usbif control interface and destroy it.
+ """
+ def cb_destroy(val):
+ self.send_be_destroy()
+ d = defer.Deferred()
+ d.addCallback(cb_destroy)
+ self.send_be_disconnect(response=d)
+
+ def send_be_disconnect(self, response=None):
+ log.debug('>UsbifBackendController>send_be_disconnect> %s', str(self))
+ msg = packMsg('usbif_be_disconnect_t',
+ { 'domid' : self.controller.dom })
+ self.writeRequest(msg, response=response)
+
+ def send_be_destroy(self, response=None):
+ log.debug('>UsbifBackendController>send_be_destroy> %s', str(self))
+ msg = packMsg('usbif_be_destroy_t',
+ { 'domid' : self.controller.dom })
+ self.writeRequest(msg, response=response)
+
+ def send_be_claim_port(self, path):
+ d=defer.Deferred()
+ log.debug(">UsbifBackendController>send_be_claim_port> about to claim port %s" % path)
+ def cb(blah): log.debug(">UsbifBackendController> Claim port completed")
+ d.addCallback(cb)
+ msg = packMsg('usbif_be_claim_port_t',
+ { 'domid' : self.controller.dom,
+ 'path' : path,
+ 'usbif_port' : self.controller.devices[path],
+ 'status' : 0})
+ self.writeRequest(msg, response=d)
+ # No need to add any callbacks, since the guest polls its virtual ports
+ # anyhow, somewhat like a UHCI controller ;-)
+ return d
+
+ def send_be_release_port(self, path):
+ d=defer.Deferred()
+ def cb(blah): log.debug(">UsbifBackendController> Release port completed")
+ d.addCallback(cb)
+ msg = packMsg('usbif_be_release_port_t',
+ { 'domid' : self.controller.dom,
+ 'path' : path })
+ self.writeRequest(msg, response)
+ # No need to add any callbacks, since the guest polls its virtual ports
+ # anyhow, somewhat like a UHCI controller ;-)
+
+ def connectInterface(self, val):
+ self.evtchn = channel.eventChannel(0, self.controller.dom)
+ log.debug(">UsbifBackendController>connectInterface> connecting usbif to event channel %s ports=%d:%d",
+ str(self), self.evtchn['port1'], self.evtchn['port2'])
+ msg = packMsg('usbif_be_connect_t',
+ { 'domid' : self.controller.dom,
+ 'evtchn' : self.evtchn['port1'],
+ 'shmem_frame' : val['shmem_frame'],
+ 'bandwidth' : 500 # XXX fix bandwidth!
+ })
+ d = defer.Deferred()
+ d.addCallback(self.respond_be_connect)
+ self.writeRequest(msg, response=d)
+
+ def respond_be_connect(self, msg):
+ """Response handler for a be_connect message.
+
+ @param msg: message
+ @type msg: xu message
+ """
+ val = unpackMsg('usbif_be_connect_t', msg)
+ log.debug('>UsbifBackendController>respond_be_connect> %s, %s', str(self), str(val))
+ d = defer.Deferred()
+ def cb(blah):
+ log.debug(">UsbifBackendController> Successfully connected USB interface for domain %d" % self.controller.dom)
+ self.controller.claim_ports()
+ d.addCallback(cb)
+ self.send_fe_interface_status_changed(d)
+
+ def send_fe_interface_status_changed(self, response=None):
+ msg = packMsg('usbif_fe_interface_status_changed_t',
+ { 'status' : USBIF_INTERFACE_STATUS_CONNECTED,
+ 'domid' : 0, ## FIXME: should be domid of backend
+ 'evtchn' : self.evtchn['port2'],
+ 'bandwidth' : 500,
+ 'num_ports' : len(self.controller.devices.keys())})
+ self.controller.writeRequest(msg, response=response)
+
+
+class UsbifControllerFactory(controller.SplitControllerFactory):
+ """Factory for creating USB interface controllers.
+ """
+
+ def __init__(self):
+ controller.ControllerFactory.__init__(self)
+ self.backendControllers = {}
+
+ def createController(self, dom, recreate=0):
+ """Create a USB device controller for a domain.
+
+ @param dom: domain
+ @type dom: int
+ @param recreate: if true it's a recreate (after xend restart)
+ @type recreate: bool
+ @return: block device controller
+ @rtype: UsbifController
+ """
+ usbif = self.getControllerByDom(dom)
+ if usbif is None:
+ usbif = UsbifController(self, dom)
+ self.addController(usbif)
+ return usbif
+
+ def getDomainDevices(self, dom):
+ """Get the block devices for a domain.
+
+ @param dom: domain
+ @type dom: int
+ @return: devices
+ @rtype: [device]
+ """
+ usbif = self.getControllerByDom(dom)
+ return (usbif and usbif.getDevices()) or []
+
+ def getDomainDevice(self, dom, vdev):
+ """Get a block device from a domain.
+
+ @param dom: domain
+ @type dom: int
+ @param vdev: device index
+ @type vdev: int
+ @return: device
+ @rtype: device
+ """
+ usbif = self.getControllerByDom(dom)
+ return (usbif and usbif.getDevice(vdev)) or None
+
+ def createBackendInterface(self, ctrl, dom, handle):
+ """Create a network device backend interface.
+
+ @param ctrl: controller
+ @param dom: backend domain
+ @param handle: interface handle
+ @return: backend interface
+ """
+ return UsbifBackendInterface(ctrl, dom)
+
+ def getBackendController(self, dom):
+ """Get the backend controller for a domain, creating
+ if necessary.
+
+ @param dom: backend domain
+ @return: backend controller
+ """
+ b = self.getBackendControllerByDomain(dom)
+ if b is None:
+ b = self.createBackendController(dom)
+ self.backendControllers[b.dom] = b
+ return b
+
+ def createBackendController(self, dom):
+ return UsbifBackendController(self, dom)
+
+class UsbifController(controller.SplitController):
+ """USB device interface controller. Handles all USB devices
+ for a domain.
+ """
+
+ def __init__(self, factory, dom):
+ """Create a USB device controller.
+ Do not call directly - use createController() on the factory instead.
+ """
+ controller.SplitController.__init__(self, factory, dom)
+ self.num_ports = 0
+ self.devices = {}
+ self.addMethod(CMSG_USBIF_FE,
+ CMSG_USBIF_FE_DRIVER_STATUS_CHANGED,
+ self.recv_fe_driver_status_changed)
+ self.addMethod(CMSG_USBIF_FE,
+ CMSG_USBIF_FE_INTERFACE_CONNECT,
+ self.recv_fe_interface_connect)
+ self.registerChannel()
+ try:
+ self.backendDomain = 0 #int(sxp.child_value(config, 'backend', '0')) TODO: configurable backends
+ except:
+ raise XendError('invalid backend domain')
+
+
+ def sxpr(self):
+ val = ['usbif', ['dom', self.dom]]
+ return val
+
+ def createBackend(self, dom, handle):
+ return UsbifBackendController(self, dom, handle)
+
+ def getDevices(self):
+ return self.devices.values()
+
+ def attachDevice(self, path, recreate=0):
+ """Add privileges for a particular device to the domain.
+ @param path: the Linux-style path to the device port
+ """
+ self.devices[path[1][1]] = self.num_ports
+ self.num_ports += 1
+ log.debug(">UsbifController>attachDevice> device: %s, port: %d" %
+ (str(path), self.num_ports ) )
+
+ backend =self.getBackendInterface(self.backendDomain)
+
+ def cb(blah):
+ log.debug(">UsbifController> Backend created")
+ pass
+ d = backend.connect()
+ d.addCallback(cb) # Chaining the claim port operation
+ return d
+
+
+ def removeDevice(self, path):
+ self.delDevice(path)
+ backend = self.getBackendInterface(self.backendDomain)
+ return backend.send_be_release_port(path)
+
+ def delDevice(self, path):
+ if path in self.devices:
+ del self.devices[path]
+
+ def attachPort(self, path, recreate=0):
+ """Attach a device to the specified interface.
+ On success the returned deferred will be called with the device.
+
+ @return: deferred
+ @rtype: Deferred
+ """
+ return self.attachDevice(path)
+
+ def destroy(self):
+ """Destroy the controller and all devices.
+ """
+ log.debug("Destroying usbif domain=%d", self.dom)
+ self.destroyBackends()
+
+ def destroyDevices(self):
+ """Destroy all devices.
+ """
+ for path in self.getDevices():
+ self.removeDevice(path)
+
+ def destroyBackends(self):
+ for backend in self.getBackendInterfaces():
+ backend.destroy()
+
+ def recv_fe_driver_status_changed(self, msg, req):
+ val = unpackMsg('usbif_fe_driver_status_changed_t', msg)
+ log.debug('>UsbifController>recv_fe_driver_status_changed> %s', str(val))
+ # For each backend?
+ msg = packMsg('usbif_fe_interface_status_changed_t',
+ { 'status' : USBIF_INTERFACE_STATUS_DISCONNECTED,
+ 'domid' : 0, ## FIXME: should be domid of backend
+ 'evtchn' : 0 })
+ d = defer.Deferred()
+ d.addCallback(self.disconnected_resp)
+ self.writeRequest(msg)
+
+ def disconnected_resp(self, msg):
+ val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
+ if val['status'] != USBIF_INTERFACE_STATUS_DISCONNECTED:
+ log.error(">UsbifController>disconnected_resp> unexpected status change")
+ else:
+ log.debug(">UsbifController>disconnected_resp> interface disconnected OK")
+
+ def recv_fe_interface_connect(self, msg, req):
+ val = unpackMsg('usbif_fe_interface_status_changed_t', msg)
+ log.debug(">UsbifController>recv_fe_interface_connect> notifying backend")
+ backend = self.getBackendInterfaceByHandle(0)
+ if backend:
+ d = backend.connectInterface(val)
+ else:
+ log.error('>UsbifController>recv_fe_interface_connect> unknown interface')
+
+ def claim_ports(self):
+ backend = self.getBackendInterfaceByHandle(0)
+ for path in self.devices.keys():
+ log.debug(">UsbifController>claim_ports> claiming port... %s" % path)
+ backend.send_be_claim_port(path)
+
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 03f815eddb..e79e02383c 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -109,6 +109,10 @@ gopts.var('cpu', val='CPU',
fn=set_int, default=None,
use="CPU to run the domain on.")
+gopts.var('vcpus', val='VCPUS',
+ fn=set_int, default=1,
+ use="# of Virtual CPUS in domain.")
+
gopts.var('cpu_weight', val='WEIGHT',
fn=set_float, default=None,
use="""Set the new domain's cpu weight.
@@ -147,15 +151,22 @@ gopts.var('pci', val='BUS,DEV,FUNC',
For example '-pci c0,02,1a'.
The option may be repeated to add more than one pci device.""")
+gopts.var('usb', val='PATH',
+ fn=append_value, default=[],
+ use="""Add a physical USB port to a domain, as specified by the path
+ to that port. This option may be repeated to add more than one port.""")
+
gopts.var('ipaddr', val="IPADDR",
fn=append_value, default=[],
use="Add an IP address to the domain.")
-gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM",
+gopts.var('vif', val="mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM",
fn=append_value, default=[],
use="""Add a network interface with the given MAC address and bridge.
The vif is configured by calling the given configuration script.
If mac is not specified a random MAC address is used.
+ The MAC address of the backend interface can be selected with be_mac.
+ If not specified then the network backend chooses it's own MAC address.
If bridge is not specified the default bridge is used.
If script is not specified the default script is used.
If backend is not specified the default backend driver domain is used.
@@ -210,6 +221,18 @@ gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
+gopts.var('memmap', val='FILE',
+ fn=set_value, default='',
+ use="Path to memap SXP file.")
+
+gopts.var('device_model', val='FILE',
+ fn=set_value, default='',
+ use="Path to device model program.")
+
+gopts.var('device_config', val='FILE',
+ fn=set_value, default='',
+ use="Path to device model configuration.")
+
def strip(pre, s):
"""Strip prefix 'pre' if present.
"""
@@ -233,7 +256,10 @@ def configure_image(config, vals):
config_image.append(['root', cmdline_root])
if vals.extra:
config_image.append(['args', vals.extra])
+ if vals.vcpus:
+ config_image.append(['vcpus', vals.vcpus])
config.append(['image', config_image ])
+
def configure_disks(config_devs, vals):
"""Create the config for disks (virtual block devices).
@@ -254,6 +280,11 @@ def configure_pci(config_devs, vals):
config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
config_devs.append(['device', config_pci])
+def configure_usb(config_devs, vals):
+ for path in vals.usb:
+ config_usb = ['usb', ['path', path]]
+ config_devs.append(['device', config_usb])
+
def randomMAC():
"""Generate a random MAC address.
@@ -285,18 +316,22 @@ def configure_vifs(config_devs, vals):
mac = d.get('mac')
if not mac:
mac = randomMAC()
+ be_mac = d.get('be_mac')
bridge = d.get('bridge')
script = d.get('script')
backend = d.get('backend')
ip = d.get('ip')
else:
mac = randomMAC()
+ be_mac = None
bridge = None
script = None
backend = None
ip = None
config_vif = ['vif']
config_vif.append(['mac', mac])
+ if be_mac:
+ config_vif.append(['be_mac', be_mac])
if bridge:
config_vif.append(['bridge', bridge])
if script:
@@ -315,6 +350,15 @@ def configure_vfr(config, vals):
config_vfr.append(['vif', ['id', idx], ['ip', ip]])
config.append(config_vfr)
+def configure_vmx(config_devs, vals):
+ """Create the config for VMX devices.
+ """
+ memmap = vals.memmap
+ device_model = vals.device_model
+ device_config = vals.device_config
+ config_devs.append(['memmap', memmap])
+ config_devs.append(['device_model', device_model])
+ config_devs.append(['device_config', device_config])
def make_config(vals):
"""Create the domain configuration.
@@ -343,6 +387,8 @@ def make_config(vals):
configure_disks(config_devs, vals)
configure_pci(config_devs, vals)
configure_vifs(config_devs, vals)
+ configure_usb(config_devs, vals)
+ configure_vmx(config_devs, vals)
config += config_devs
return config
@@ -383,7 +429,7 @@ def preprocess_vifs(opts, vals):
(k, v) = b.strip().split('=', 1)
k = k.strip()
v = v.strip()
- if k not in ['mac', 'bridge', 'script', 'backend', 'ip']:
+ if k not in ['mac', 'be_mac', 'bridge', 'script', 'backend', 'ip']:
opts.err('Invalid vif specifier: ' + vif)
d[k] = v
vifs.append(d)