mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
g/c unused xcs.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
1 parent
c3c71f3f6a
commit
7cded01029
17 files changed
+1
-2771
No files matched your search
@@ -147,8 +147,6 @@
|
||||
^tools/vtpm_manager/manager/vtpm_managerd
|
||||
^tools/web-shutdown\.tap$
|
||||
^tools/x2d2/minixend$
|
||||
^tools/xcs/xcs$
|
||||
^tools/xcs/xcsdump$
|
||||
^tools/xcutils/xc_restore$
|
||||
^tools/xcutils/xc_save$
|
||||
^tools/xenstat/xentop/xentop$
|
||||
@@ -166,7 +164,6 @@
|
||||
^tools/xenstore/xs_test$
|
||||
^tools/xenstore/xs_watch_stress$
|
||||
^tools/xentrace/xentrace$
|
||||
^tools/xfrd/xfrd$
|
||||
^xen/BLOG$
|
||||
^xen/TAGS$
|
||||
^xen/arch/x86/asm-offsets\.s$
|
||||
|
||||
@@ -7,7 +7,6 @@ SUBDIRS += xenstore
|
||||
SUBDIRS += misc
|
||||
SUBDIRS += examples
|
||||
SUBDIRS += xentrace
|
||||
SUBDIRS += xcs
|
||||
SUBDIRS += xcutils
|
||||
SUBDIRS += firmware
|
||||
SUBDIRS += security
|
||||
|
||||
@@ -4,7 +4,6 @@ include $(XEN_ROOT)/Config.mk
|
||||
|
||||
XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
|
||||
XEN_LIBXC = $(XEN_ROOT)/tools/libxc
|
||||
XEN_XCS = $(XEN_ROOT)/tools/xcs
|
||||
XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore
|
||||
XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ if ! [ -e /proc/xen/privcmd ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Wait for Xend and xcs to be up
|
||||
# Wait for Xend to be up
|
||||
function await_daemons_up
|
||||
{
|
||||
i=1
|
||||
|
||||
@@ -26,11 +26,6 @@ import signal
|
||||
import time
|
||||
import commands
|
||||
|
||||
XCS_PATH = "/var/lib/xen/xcs_socket"
|
||||
XCS_EXEC = "/usr/sbin/xcs"
|
||||
XCS_PIDFILE = "/var/run/xcs.pid"
|
||||
XCS_ARGS = (XCS_EXEC, "-p", XCS_PIDFILE)
|
||||
|
||||
# add fallback path for non-native python path installs if needed
|
||||
sys.path.append('/usr/lib/python')
|
||||
sys.path.append('/usr/lib64/python')
|
||||
@@ -70,52 +65,6 @@ def check_user():
|
||||
hline()
|
||||
raise CheckError("invalid user")
|
||||
|
||||
def xcs_running():
|
||||
""" See if the control switch is running.
|
||||
"""
|
||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect( (XCS_PATH) )
|
||||
s.close()
|
||||
except:
|
||||
try:
|
||||
os.remove(XCS_PIDFILE)
|
||||
except:
|
||||
pass
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def start_xcs():
|
||||
if (not xcs_running()):
|
||||
if os.fork() == 0 :
|
||||
if not os.path.isdir(os.path.dirname(XCS_PATH)):
|
||||
os.makedirs(os.path.dirname(XCS_PATH))
|
||||
try:
|
||||
os.execvp(XCS_EXEC, XCS_ARGS)
|
||||
except:
|
||||
hline()
|
||||
msg("Tried to start xcs, but failed. Is it installed?")
|
||||
hline()
|
||||
raise CheckError("couldn't start xcs")
|
||||
for n in range(10) :
|
||||
if (xcs_running()):
|
||||
break
|
||||
time.sleep(0.1)
|
||||
else :
|
||||
hline()
|
||||
msg("Failed to start the control interface switch.")
|
||||
hline()
|
||||
raise CheckError("xcs not running")
|
||||
|
||||
def stop_xcs():
|
||||
try:
|
||||
xcs_pidfile = open(XCS_PIDFILE)
|
||||
xcs_pid = int(xcs_pidfile.read().strip())
|
||||
os.kill(xcs_pid, signal.SIGTERM)
|
||||
xcs_pidfile.close()
|
||||
except:
|
||||
return
|
||||
|
||||
def start_xenstored():
|
||||
XENSTORED_TRACE = os.getenv("XENSTORED_TRACE")
|
||||
cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"
|
||||
@@ -141,19 +90,16 @@ def main():
|
||||
pid, status = os.wait()
|
||||
return status >> 8
|
||||
elif sys.argv[1] == 'start':
|
||||
start_xcs()
|
||||
start_xenstored()
|
||||
start_consoled()
|
||||
return daemon.start()
|
||||
elif sys.argv[1] == 'trace_start':
|
||||
start_xcs()
|
||||
start_xenstored()
|
||||
start_consoled()
|
||||
return daemon.start(trace=1)
|
||||
elif sys.argv[1] == 'stop':
|
||||
return daemon.stop()
|
||||
elif sys.argv[1] == 'restart':
|
||||
start_xcs()
|
||||
start_xenstored()
|
||||
start_consoled()
|
||||
return daemon.stop() or daemon.start()
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# Makefile for XCS
|
||||
# Andrew Warfield, 2004
|
||||
|
||||
XEN_ROOT=../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
XCS_INSTALL_DIR = /usr/sbin
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROG = $(INSTALL) -m0755
|
||||
INSTALL_DIR = $(INSTALL) -d -m0755
|
||||
|
||||
CFLAGS += -Wall -Werror -g3 -D _XOPEN_SOURCE=600
|
||||
|
||||
CFLAGS += -I $(XEN_XC)
|
||||
CFLAGS += -I $(XEN_LIBXC)
|
||||
|
||||
SRCS :=
|
||||
SRCS += ctrl_interface.c
|
||||
SRCS += bindings.c
|
||||
SRCS += connection.c
|
||||
SRCS += evtchn.c
|
||||
SRCS += xcs.c
|
||||
|
||||
HDRS = $(wildcard *.h)
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
BIN = xcs
|
||||
|
||||
all: $(BIN) xcsdump
|
||||
|
||||
clean:
|
||||
$(RM) *.a *.so *.o *.rpm $(BIN) xcsdump
|
||||
|
||||
xcsdump: xcsdump.c dump.c
|
||||
$(CC) $(CFLAGS) -o xcsdump xcsdump.c -L$(XEN_LIBXC) \
|
||||
ctrl_interface.c evtchn.c dump.c -lxenctrl
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -lxenctrl
|
||||
|
||||
$(OBJS): $(HDRS)
|
||||
|
||||
install: xcs xcsdump
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/$(XCS_INSTALL_DIR)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/include
|
||||
$(INSTALL_PROG) xcs $(DESTDIR)/$(XCS_INSTALL_DIR)
|
||||
$(INSTALL_PROG) xcsdump $(DESTDIR)/$(XCS_INSTALL_DIR)
|
||||
$(INSTALL_PROG) xcs_proto.h $(DESTDIR)/usr/include
|
||||
@@ -1,179 +0,0 @@
|
||||
/* bindings.c
|
||||
*
|
||||
* Manage subscriptions for the control interface switch.
|
||||
*
|
||||
* (c) 2004, Andrew Warfield
|
||||
*
|
||||
*/
|
||||
|
||||
/* Interfaces:
|
||||
*
|
||||
* xcs_bind (port, type, connection)
|
||||
* - Register connection to receive messages of this type.
|
||||
* xcs_unbind (port, type, connection)
|
||||
* - Remove an existing registration. (Must be an exact match)
|
||||
* xcs_lookup (port, type)
|
||||
* - Return a list of connections matching a registration.
|
||||
*
|
||||
* - All connections have a connection.bindings list of current bindings.
|
||||
* - (port, type) pairs may be wildcarded with -1.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "xcs.h"
|
||||
|
||||
|
||||
typedef struct binding_ent_st {
|
||||
connection_t *con;
|
||||
struct binding_ent_st *next;
|
||||
} binding_ent_t;
|
||||
|
||||
#define BINDING_TABLE_SIZE 1024
|
||||
|
||||
static binding_ent_t *binding_table[BINDING_TABLE_SIZE];
|
||||
|
||||
#define PORT_WILD(_ent) ((_ent)->port == PORT_WILDCARD)
|
||||
#define TYPE_WILD(_ent) ((_ent)->type == TYPE_WILDCARD)
|
||||
#define FULLY_WILD(_ent) (PORT_WILD(_ent) && TYPE_WILD(_ent))
|
||||
|
||||
#define BINDING_HASH(_key) \
|
||||
((((_key)->port * 11) ^ (_key)->type) % BINDING_TABLE_SIZE)
|
||||
|
||||
|
||||
void init_bindings(void)
|
||||
{
|
||||
memset(binding_table, 0, sizeof(binding_table));
|
||||
}
|
||||
|
||||
static int table_add(binding_ent_t *table[],
|
||||
connection_t *con,
|
||||
binding_key_t *key)
|
||||
{
|
||||
binding_ent_t **curs, *ent;
|
||||
|
||||
curs = &table[BINDING_HASH(key)];
|
||||
|
||||
while (*curs != NULL) {
|
||||
if ((*curs)->con == con) {
|
||||
DPRINTF("Tried to add an ent that already existed.\n");
|
||||
goto done;
|
||||
}
|
||||
curs = &(*curs)->next;
|
||||
}
|
||||
|
||||
if (connection_add_binding(con, key) != 0)
|
||||
{
|
||||
DPRINTF("couldn't add binding on connection (%lu)\n", con->id);
|
||||
goto fail;
|
||||
}
|
||||
ent = (binding_ent_t *)malloc(sizeof(binding_ent_t));
|
||||
if (ent == 0) {
|
||||
DPRINTF("couldn't alloc binding ent!\n");
|
||||
goto fail;
|
||||
}
|
||||
ent->con = con;
|
||||
ent->next = NULL;
|
||||
*curs = ent;
|
||||
|
||||
done:
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static inline int binding_has_colliding_hashes(connection_t *con,
|
||||
binding_key_t *key)
|
||||
{
|
||||
int hash, count = 0;
|
||||
binding_key_ent_t *ent;
|
||||
|
||||
ent = con->bindings;
|
||||
hash = BINDING_HASH(key);
|
||||
|
||||
while (ent != NULL) {
|
||||
if (BINDING_HASH(&ent->key) == hash) count ++;
|
||||
ent = ent->next;
|
||||
}
|
||||
|
||||
return (count > 1);
|
||||
}
|
||||
static int table_remove(binding_ent_t *table[],
|
||||
connection_t *con,
|
||||
binding_key_t *key)
|
||||
{
|
||||
binding_ent_t **curs, *ent;
|
||||
|
||||
if (!binding_has_colliding_hashes(con, key))
|
||||
{
|
||||
|
||||
curs = &table[BINDING_HASH(key)];
|
||||
|
||||
while ((*curs != NULL) && ((*curs)->con != con))
|
||||
curs = &(*curs)->next;
|
||||
|
||||
if (*curs != NULL) {
|
||||
ent = *curs;
|
||||
*curs = (*curs)->next;
|
||||
free(ent);
|
||||
}
|
||||
}
|
||||
|
||||
connection_remove_binding(con, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xcs_bind(connection_t *con, int port, u16 type)
|
||||
{
|
||||
binding_key_t key;
|
||||
|
||||
key.port = port;
|
||||
key.type = type;
|
||||
|
||||
return table_add(binding_table, con, &key);
|
||||
}
|
||||
|
||||
int xcs_unbind(connection_t *con, int port, u16 type)
|
||||
{
|
||||
binding_key_t key;
|
||||
|
||||
key.port = port;
|
||||
key.type = type;
|
||||
|
||||
return table_remove(binding_table, con, &key);
|
||||
}
|
||||
|
||||
|
||||
static void for_each_binding(binding_ent_t *list, binding_key_t *key,
|
||||
void (*f)(connection_t *, void *), void *arg)
|
||||
{
|
||||
while (list != NULL)
|
||||
{
|
||||
if (connection_has_binding(list->con, key))
|
||||
f(list->con, arg);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *),
|
||||
void *arg)
|
||||
{
|
||||
binding_key_t key;
|
||||
|
||||
key.port = port; key.type = type;
|
||||
for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
|
||||
|
||||
key.port = port; key.type = TYPE_WILDCARD;
|
||||
for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
|
||||
|
||||
key.port = PORT_WILDCARD; key.type = type;
|
||||
for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
|
||||
|
||||
key.port = PORT_WILDCARD; key.type = TYPE_WILDCARD;
|
||||
for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* connection.c
|
||||
*
|
||||
* State associated with a client connection to xcs.
|
||||
*
|
||||
* Copyright (c) 2004, Andrew Warfield
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "xcs.h"
|
||||
|
||||
connection_t *connection_list = NULL;
|
||||
|
||||
#define CONNECTED(_c) (((_c)->ctrl_fd != -1) || ((_c)->data_fd != -1))
|
||||
|
||||
connection_t *get_con_by_session(unsigned long session_id)
|
||||
{
|
||||
connection_t **c, *ent = NULL;
|
||||
|
||||
c = &connection_list;
|
||||
|
||||
DPRINTF("looking for id: %lu : %lu\n", session_id, (*c)->id);
|
||||
|
||||
while (*c != NULL)
|
||||
{
|
||||
if ((*c)->id == session_id)
|
||||
return (*c);
|
||||
c = &(*c)->next;
|
||||
}
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
connection_t *connection_new()
|
||||
{
|
||||
connection_t *con;
|
||||
|
||||
con = (connection_t *)malloc(sizeof(connection_t));
|
||||
if (con == NULL)
|
||||
{
|
||||
DPRINTF("couldn't allocate a new connection\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
con->bindings = NULL;
|
||||
con->data_fd = -1;
|
||||
con->ctrl_fd = -1;
|
||||
|
||||
/* connections need a unique session id.
|
||||
* - this approach probably gets fixed later, but for the moment
|
||||
* is unique, and clearly identifies a connection.
|
||||
*/
|
||||
con->id = (unsigned long)con;
|
||||
|
||||
/* add it to the connection list */
|
||||
con->next = connection_list;
|
||||
connection_list = con;
|
||||
|
||||
return (con);
|
||||
}
|
||||
|
||||
void connection_free(connection_t *con)
|
||||
{
|
||||
/* first free all subscribed bindings: */
|
||||
|
||||
while (con->bindings != NULL)
|
||||
xcs_unbind(con, con->bindings->key.port, con->bindings->key.type);
|
||||
|
||||
/* now free the connection. */
|
||||
free(con);
|
||||
}
|
||||
|
||||
int connection_add_binding(connection_t *con, binding_key_t *key)
|
||||
{
|
||||
binding_key_ent_t *key_ent;
|
||||
|
||||
key_ent = (binding_key_ent_t *)malloc(sizeof(binding_key_ent_t));
|
||||
if (key_ent == NULL)
|
||||
{
|
||||
DPRINTF("couldn't alloc key in connection_add_binding\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key_ent->key = *key;
|
||||
key_ent->next = con->bindings;
|
||||
con->bindings = key_ent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int connection_remove_binding(connection_t *con, binding_key_t *key)
|
||||
{
|
||||
binding_key_ent_t *key_ent;
|
||||
binding_key_ent_t **curs = &con->bindings;
|
||||
|
||||
while ((*curs != NULL) && (!BINDING_KEYS_EQUAL(&(*curs)->key, key)))
|
||||
curs = &(*curs)->next;
|
||||
|
||||
if (*curs != NULL) {
|
||||
key_ent = *curs;
|
||||
*curs = (*curs)->next;
|
||||
free(key_ent);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int connection_has_binding(connection_t *con, binding_key_t *key)
|
||||
{
|
||||
binding_key_ent_t *ent;
|
||||
int ret = 0;
|
||||
|
||||
ent = con->bindings;
|
||||
|
||||
while (ent != NULL)
|
||||
{
|
||||
if (BINDING_KEYS_EQUAL(key, &ent->key))
|
||||
{
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
ent = ent->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void gc_connection_list(void)
|
||||
{
|
||||
connection_t **c, *ent = NULL;
|
||||
struct timeval now, delta;
|
||||
|
||||
c = &connection_list;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
while ( *c != NULL )
|
||||
{
|
||||
if ( !CONNECTED(*c) )
|
||||
{
|
||||
timersub(&now, &(*c)->disconnect_time, &delta);
|
||||
if ( delta.tv_sec >= XCS_SESSION_TIMEOUT )
|
||||
{
|
||||
DPRINTF(" : Freeing connection %lu after %lds\n",
|
||||
(*c)->id, delta.tv_sec);
|
||||
ent = *c;
|
||||
*c = (*c)->next;
|
||||
connection_free(ent);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c = &(*c)->next;
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
/* control_interface.c
|
||||
*
|
||||
* Interfaces to control message rings to VMs.
|
||||
*
|
||||
* Most of this is directly based on the original xu interface to python
|
||||
* written by Keir Fraser.
|
||||
*
|
||||
* (c) 2004, Andrew Warfield
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include "xcs.h"
|
||||
|
||||
static int xc_handle = -1;
|
||||
|
||||
/* Called at start-of-day when using the control channel interface. */
|
||||
int ctrl_chan_init(void)
|
||||
{
|
||||
if ( (xc_handle = xc_interface_open()) == -1 )
|
||||
{
|
||||
DPRINTF("Could not open Xen control interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int ctrl_chan_notify(control_channel_t *cc)
|
||||
{
|
||||
return xc_evtchn_send(xc_handle, cc->local_port);
|
||||
}
|
||||
|
||||
int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *dmsg)
|
||||
{
|
||||
control_msg_t *smsg;
|
||||
RING_IDX c = cc->tx_ring.req_cons;
|
||||
|
||||
if ( !RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring) )
|
||||
{
|
||||
DPRINTF("no request to read\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rmb(); /* make sure we see the data associated with the request */
|
||||
smsg = RING_GET_REQUEST(&cc->tx_ring, c);
|
||||
memcpy(&dmsg->msg, smsg, sizeof(*smsg));
|
||||
if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
|
||||
dmsg->msg.length = sizeof(dmsg->msg.msg);
|
||||
cc->tx_ring.req_cons++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctrl_chan_write_request(control_channel_t *cc,
|
||||
xcs_control_msg_t *smsg)
|
||||
{
|
||||
control_msg_t *dmsg;
|
||||
RING_IDX p = cc->rx_ring.req_prod_pvt;
|
||||
|
||||
if ( RING_FULL(&cc->rx_ring) )
|
||||
{
|
||||
DPRINTF("no space to write request");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dmsg = RING_GET_REQUEST(&cc->rx_ring, p);
|
||||
memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
|
||||
|
||||
wmb();
|
||||
cc->rx_ring.req_prod_pvt++;
|
||||
RING_PUSH_REQUESTS(&cc->rx_ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *dmsg)
|
||||
{
|
||||
control_msg_t *smsg;
|
||||
RING_IDX c = cc->rx_ring.rsp_cons;
|
||||
|
||||
if ( !RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring) )
|
||||
{
|
||||
DPRINTF("no response to read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rmb(); /* make sure we see the data associated with the request */
|
||||
smsg = RING_GET_RESPONSE(&cc->rx_ring, c);
|
||||
memcpy(&dmsg->msg, smsg, sizeof(*smsg));
|
||||
if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
|
||||
dmsg->msg.length = sizeof(dmsg->msg.msg);
|
||||
cc->rx_ring.rsp_cons++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctrl_chan_write_response(control_channel_t *cc,
|
||||
xcs_control_msg_t *smsg)
|
||||
{
|
||||
control_msg_t *dmsg;
|
||||
RING_IDX p = cc->tx_ring.rsp_prod_pvt;
|
||||
|
||||
/* akw: if the ring is synchronous, you should never need this test! */
|
||||
/* (but it was in the original code... ) */
|
||||
if ( cc->tx_ring.req_cons == cc->tx_ring.rsp_prod_pvt )
|
||||
{
|
||||
DPRINTF("no space to write response");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dmsg = RING_GET_RESPONSE(&cc->tx_ring, p);
|
||||
memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
|
||||
|
||||
wmb();
|
||||
cc->tx_ring.rsp_prod_pvt++;
|
||||
RING_PUSH_RESPONSES(&cc->tx_ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctrl_chan_request_to_read(control_channel_t *cc)
|
||||
{
|
||||
return (RING_HAS_UNCONSUMED_REQUESTS(&cc->tx_ring));
|
||||
}
|
||||
|
||||
int ctrl_chan_space_to_write_request(control_channel_t *cc)
|
||||
{
|
||||
return (!(RING_FULL(&cc->rx_ring)));
|
||||
}
|
||||
|
||||
int ctrl_chan_response_to_read(control_channel_t *cc)
|
||||
{
|
||||
return (RING_HAS_UNCONSUMED_RESPONSES(&cc->rx_ring));
|
||||
}
|
||||
|
||||
int ctrl_chan_space_to_write_response(control_channel_t *cc)
|
||||
{
|
||||
/* again, there is something fishy here. */
|
||||
return ( cc->tx_ring.req_cons != cc->tx_ring.rsp_prod_pvt );
|
||||
}
|
||||
|
||||
int ctrl_chan_connect(control_channel_t *cc)
|
||||
{
|
||||
xc_dominfo_t info;
|
||||
|
||||
if ( cc->connected )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (xc_domain_getinfo(xc_handle, cc->remote_dom, 1, &info) != 1) ||
|
||||
(info.domid != cc->remote_dom) )
|
||||
{
|
||||
DPRINTF("Failed to obtain domain status");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cc->interface =
|
||||
map_control_interface(xc_handle, info.shared_info_frame,
|
||||
cc->remote_dom);
|
||||
|
||||
if ( cc->interface == NULL )
|
||||
{
|
||||
DPRINTF("Failed to map domain control interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Synchronise ring indexes. */
|
||||
BACK_RING_ATTACH(&cc->tx_ring, &cc->interface->tx_ring, CONTROL_RING_MEM);
|
||||
FRONT_RING_ATTACH(&cc->rx_ring, &cc->interface->rx_ring, CONTROL_RING_MEM);
|
||||
|
||||
cc->connected = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ctrl_chan_disconnect(control_channel_t *cc)
|
||||
{
|
||||
if ( cc->connected )
|
||||
unmap_control_interface(xc_handle, cc->interface);
|
||||
cc->connected = 0;
|
||||
}
|
||||
|
||||
|
||||
control_channel_t *ctrl_chan_new(u32 dom, int local_port, int remote_port)
|
||||
{
|
||||
control_channel_t *cc;
|
||||
|
||||
cc = (control_channel_t *)malloc(sizeof(control_channel_t));
|
||||
if ( cc == NULL ) return NULL;
|
||||
|
||||
cc->connected = 0;
|
||||
cc->remote_dom = dom;
|
||||
|
||||
if ( dom == 0 )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
else if ( xc_evtchn_bind_interdomain(xc_handle,
|
||||
DOMID_SELF, dom,
|
||||
&local_port, &remote_port) != 0 )
|
||||
{
|
||||
DPRINTF("Could not open channel to domain");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cc->local_port = local_port;
|
||||
cc->remote_port = remote_port;
|
||||
|
||||
if ( ctrl_chan_connect(cc) != 0 )
|
||||
goto fail;
|
||||
|
||||
return cc;
|
||||
|
||||
fail:
|
||||
if ( dom != 0 )
|
||||
(void)xc_evtchn_close(xc_handle, DOMID_SELF, local_port);
|
||||
|
||||
free(cc);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ctrl_chan_free(control_channel_t *cc)
|
||||
{
|
||||
ctrl_chan_disconnect(cc);
|
||||
if ( cc->remote_dom != 0 )
|
||||
(void)xc_evtchn_close(xc_handle, DOMID_SELF, cc->local_port);
|
||||
free(cc);
|
||||
}
|
||||
|
||||
|
||||
/* other libxc commands: */
|
||||
|
||||
int ctrl_chan_bind_virq(int virq, int *port)
|
||||
{
|
||||
return xc_evtchn_bind_virq(xc_handle, virq, port);
|
||||
}
|
||||
@@ -1,506 +0,0 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "dump.h"
|
||||
|
||||
#define str(a) # a
|
||||
#define error(a, ...) do { \
|
||||
_error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
|
||||
exit(1); \
|
||||
} while (0)
|
||||
#define warn(a, ...) do { \
|
||||
_error("%s:%s():L%d: " a, __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__);\
|
||||
} while (0)
|
||||
#define debug(a, ...) do { \
|
||||
_error(a, ## __VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
void _error(const char *fmt, ...);
|
||||
|
||||
#define debug_begin(a, b) debug("CMSG_" a "_" b " {")
|
||||
#define debug_end(a, b) debug("}")
|
||||
#define debug_field(a, b, c) debug("\t." str(b) " = " c, a->b)
|
||||
#define debug_field_mac(a, b) \
|
||||
debug("\t." str(b) " = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", \
|
||||
a->b[0], a->b[1], a->b[2], a->b[3], a->b[4], a->b[5])
|
||||
|
||||
#define debug_dump(a, b, c) debug_hex("\t." str(b) " = ", a->b, a->c)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int strcount(const char *str, char ch)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
for (i = 0; str[i]; i++) {
|
||||
if (str[i] == ch) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void debug_hex(const char *info, const uint8_t *data, size_t length)
|
||||
{
|
||||
int indent = strlen(info) + (strcount(info, '\t') * 8 - 1);
|
||||
int words_per_row = (2 * (80 - indent - 2) / 7) & ~1;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < length; i += words_per_row) {
|
||||
size_t ind;
|
||||
|
||||
if (i == 0) {
|
||||
fprintf(stderr, "%s", info);
|
||||
} else {
|
||||
int j;
|
||||
for (j = 0; j < indent; j++) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
|
||||
for (ind = 0; ind < words_per_row; ind++) {
|
||||
if (ind % 2 == 0) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
|
||||
if (i + ind < length) {
|
||||
fprintf(stderr, "%.2X", data[i + ind]);
|
||||
} else {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, " ");
|
||||
|
||||
for (ind = 0; ind < words_per_row; ind++) {
|
||||
if (i + ind < length) {
|
||||
if (isprint(data[i + ind])) {
|
||||
fprintf(stderr, "%c", data[i + ind]);
|
||||
} else {
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void dump_msg(const control_msg_t *msg, uint64_t flags)
|
||||
{
|
||||
if ((flags & (1 << msg->type)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->type) {
|
||||
case CMSG_CONSOLE:
|
||||
if (msg->subtype == CMSG_CONSOLE_DATA) {
|
||||
debug_begin("CONSOLE", "DATA");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("CONSOLE", "DATA");
|
||||
} else {
|
||||
debug_begin("CONSOLE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("CONSOLE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_BLKIF_BE:
|
||||
if (msg->subtype == CMSG_BLKIF_BE_CREATE) {
|
||||
blkif_be_create_t *load;
|
||||
load = (blkif_be_create_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "CREATE");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "CREATE");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_DESTROY) {
|
||||
blkif_be_destroy_t *load;
|
||||
load = (blkif_be_destroy_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "DESTROY");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "DESTROY");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_CONNECT) {
|
||||
blkif_be_connect_t *load;
|
||||
load = (blkif_be_connect_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "CONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, shmem_frame, "%lu");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "CONNECT");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_DISCONNECT) {
|
||||
blkif_be_disconnect_t *load;
|
||||
load = (blkif_be_disconnect_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "DISCONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "DISCONNECT");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_VBD_CREATE) {
|
||||
blkif_be_vbd_create_t *load;
|
||||
load = (blkif_be_vbd_create_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "VBD_CREATE");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, pdevice, "%u");
|
||||
debug_field(load, vdevice, "%u");
|
||||
debug_field(load, readonly, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "VBD_CREATE");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_VBD_DESTROY) {
|
||||
blkif_be_vbd_destroy_t *load;
|
||||
load = (blkif_be_vbd_destroy_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "VBD_DESTROY");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, blkif_handle, "%u");
|
||||
debug_field(load, vdevice, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "VBD_DESTROY");
|
||||
} else if (msg->subtype == CMSG_BLKIF_BE_DRIVER_STATUS) {
|
||||
blkif_be_driver_status_t *load;
|
||||
load = (blkif_be_driver_status_t *)msg->msg;
|
||||
debug_begin("BLKIF_BE", "DRIVER_STATUS");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("BLKIF_BE", "DRIVER_STATUS");
|
||||
} else {
|
||||
debug_begin("BLKIF_BE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("BLKIF_BE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_BLKIF_FE:
|
||||
if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_STATUS) {
|
||||
blkif_fe_interface_status_t *load;
|
||||
load = (blkif_fe_interface_status_t *)msg->msg;
|
||||
debug_begin("BLKIF_FE", "INTERFACE_STATUS");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_end("BLKIF_FE", "INTERFACE_STATUS");
|
||||
} else if (msg->subtype == CMSG_BLKIF_FE_DRIVER_STATUS) {
|
||||
blkif_fe_driver_status_t *load;
|
||||
load = (blkif_fe_driver_status_t *)msg->msg;
|
||||
debug_begin("BLKIF_FE", "DRIVER_STATUS");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, max_handle, "%u");
|
||||
debug_end("BLKIF_FE", "DRIVER_STATUS");
|
||||
} else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT) {
|
||||
blkif_fe_interface_connect_t *load;
|
||||
load = (blkif_fe_interface_connect_t *)msg->msg;
|
||||
debug_begin("BLKIF_FE", "INTERFACE_CONNECT");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, shmem_frame, "%lu");
|
||||
debug_end("BLKIF_FE", "INTERFACE_CONNECT");
|
||||
} else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_DISCONNECT) {
|
||||
blkif_fe_interface_disconnect_t *load;
|
||||
load = (blkif_fe_interface_disconnect_t *)msg->msg;
|
||||
debug_begin("BLKIF_FE", "INTERFACE_DISCONNECT");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_end("BLKIF_FE", "INTERFACE_DISCONNECT");
|
||||
} else if (msg->subtype == CMSG_BLKIF_FE_INTERFACE_QUERY) {
|
||||
blkif_fe_interface_query_t *load;
|
||||
load = (blkif_fe_interface_query_t *)msg->msg;
|
||||
debug_begin("BLKIF_FE", "INTERFACE_QUERY");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_end("BLKIF_FE", "INTERFACE_QUERY");
|
||||
} else {
|
||||
debug_begin("BLKIF_FE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("BLKIF_FE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_NETIF_BE:
|
||||
if (msg->subtype == CMSG_NETIF_BE_CREATE) {
|
||||
netif_be_create_t *load;
|
||||
load = (netif_be_create_t *)msg->msg;
|
||||
debug_begin("NETIF_BE", "CREATE");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, netif_handle, "%u");
|
||||
debug_field_mac(load, mac);
|
||||
debug_field_mac(load, be_mac);
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("NETIF_BE", "CREATE");
|
||||
} else if (msg->subtype == CMSG_NETIF_BE_DESTROY) {
|
||||
netif_be_destroy_t *load;
|
||||
load = (netif_be_destroy_t *)msg->msg;
|
||||
debug_begin("NETIF_BE", "DESTROY");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, netif_handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("NETIF_BE", "DESTROY");
|
||||
} else if (msg->subtype == CMSG_NETIF_BE_CONNECT) {
|
||||
netif_be_connect_t *load;
|
||||
load = (netif_be_connect_t *)msg->msg;
|
||||
debug_begin("NETIF_BE", "CONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, netif_handle, "%u");
|
||||
debug_field(load, tx_shmem_frame, "%lu");
|
||||
debug_field(load, rx_shmem_frame, "%lu");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("NETIF_BE", "CONNECT");
|
||||
} else if (msg->subtype == CMSG_NETIF_BE_DISCONNECT) {
|
||||
netif_be_disconnect_t *load;
|
||||
load = (netif_be_disconnect_t *)msg->msg;
|
||||
debug_begin("NETIF_BE", "DISCONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, netif_handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("NETIF_BE", "DISCONNECT");
|
||||
} else if (msg->subtype == CMSG_NETIF_BE_DRIVER_STATUS) {
|
||||
netif_be_driver_status_t *load;
|
||||
load = (netif_be_driver_status_t *)msg->msg;
|
||||
debug_begin("NETIF_BE", "DRIVER_STATUS");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("NETIF_BE", "DRIVER_STATUS");
|
||||
} else {
|
||||
debug_begin("NETIF_BE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("NETIF_BE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_NETIF_FE:
|
||||
if (msg->subtype == CMSG_NETIF_FE_INTERFACE_STATUS) {
|
||||
netif_fe_interface_status_t *load;
|
||||
load = (netif_fe_interface_status_t *)msg->msg;
|
||||
debug_begin("NETIF_FE", "INTERFACE_STATUS");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field_mac(load, mac);
|
||||
debug_field(load, domid, "%u");
|
||||
debug_end("NETIF_FE", "INTERFACE_STATUS");
|
||||
} else if (msg->subtype == CMSG_NETIF_FE_DRIVER_STATUS) {
|
||||
netif_fe_driver_status_t *load;
|
||||
load = (netif_fe_driver_status_t *)msg->msg;
|
||||
debug_begin("NETIF_FE", "DRIVER_STATUS");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, max_handle, "%u");
|
||||
debug_end("NETIF_FE", "DRIVER_STATUS");
|
||||
} else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_CONNECT) {
|
||||
netif_fe_interface_connect_t *load;
|
||||
load = (netif_fe_interface_connect_t *)msg->msg;
|
||||
debug_begin("NETIF_FE", "INTERFACE_CONNECT");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, tx_shmem_frame, "%lu");
|
||||
debug_field(load, rx_shmem_frame, "%lu");
|
||||
debug_end("NETIF_FE", "INTERFACE_CONNECT");
|
||||
} else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_DISCONNECT) {
|
||||
netif_fe_interface_disconnect_t *load;
|
||||
load = (netif_fe_interface_disconnect_t *)msg->msg;
|
||||
debug_begin("NETIF_FE", "INTERFACE_DISCONNECT");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_end("NETIF_FE", "INTERFACE_DISCONNECT");
|
||||
} else if (msg->subtype == CMSG_NETIF_FE_INTERFACE_QUERY) {
|
||||
netif_fe_interface_query_t *load;
|
||||
load = (netif_fe_interface_query_t *)msg->msg;
|
||||
debug_begin("NETIF_FE", "INTERFACE_QUERY");
|
||||
debug_field(load, handle, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field_mac(load, mac);
|
||||
debug_field(load, domid, "%u");
|
||||
debug_end("NETIF_FE", "INTERFACE_QUERY");
|
||||
} else {
|
||||
debug_begin("NETIF_FE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("NETIF_FE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_SHUTDOWN:
|
||||
if (msg->subtype == CMSG_SHUTDOWN_POWEROFF) {
|
||||
debug_begin("SHUTDOWN", "POWEROFF");
|
||||
debug_end("SHUTDOWN", "POWEROFF");
|
||||
} else if (msg->subtype == CMSG_SHUTDOWN_REBOOT) {
|
||||
debug_begin("SHUTDOWN", "REBOOT");
|
||||
debug_end("SHUTDOWN", "REBOOT");
|
||||
} else if (msg->subtype == CMSG_SHUTDOWN_SUSPEND) {
|
||||
debug_begin("SHUTDOWN", "SUSPEND");
|
||||
debug_end("SHUTDOWN", "SUSPEND");
|
||||
} else if (msg->subtype == CMSG_SHUTDOWN_SYSRQ) {
|
||||
debug_begin("SHUTDOWN", "SYSRQ");
|
||||
debug_end("SHUTDOWN", "SYSRQ");
|
||||
} else {
|
||||
debug_begin("SHUTDOWN", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("SHUTDOWN", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_MEM_REQUEST:
|
||||
if (msg->subtype == CMSG_MEM_REQUEST_SET) {
|
||||
mem_request_t *load;
|
||||
load = (mem_request_t *)msg->msg;
|
||||
debug_begin("MEM_REQUEST", "SET");
|
||||
debug_field(load, target, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("MEM_REQUEST", "SET");
|
||||
} else {
|
||||
debug_begin("MEM_REQUEST", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("MEM_REQUEST", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_USBIF_BE:
|
||||
if (msg->subtype == CMSG_USBIF_BE_CREATE) {
|
||||
usbif_be_create_t *load;
|
||||
load = (usbif_be_create_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "CREATE");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_BE", "CREATE");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_DESTROY) {
|
||||
usbif_be_destroy_t *load;
|
||||
load = (usbif_be_destroy_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "DESTROY");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_BE", "DESTROY");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_CONNECT) {
|
||||
usbif_be_connect_t *load;
|
||||
load = (usbif_be_connect_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "CONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, shmem_frame, "%lu");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, bandwidth, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_BE", "CONNECT");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_DISCONNECT) {
|
||||
usbif_be_disconnect_t *load;
|
||||
load = (usbif_be_disconnect_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "DISCONNECT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_BE", "DISCONNECT");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_CLAIM_PORT) {
|
||||
usbif_be_claim_port_t *load;
|
||||
load = (usbif_be_claim_port_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "CLAIM_PORT");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, usbif_port, "%u");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, path, "%s");
|
||||
debug_end("USBIF_BE", "CLAIM_PORT");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_RELEASE_PORT) {
|
||||
usbif_be_release_port_t *load;
|
||||
load = (usbif_be_release_port_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "RELEASE_PORT");
|
||||
debug_field(load, path, "%s");
|
||||
debug_end("USBIF_BE", "RELEASE_PORT");
|
||||
} else if (msg->subtype == CMSG_USBIF_BE_DRIVER_STATUS_CHANGED) {
|
||||
usbif_be_driver_status_changed_t *load;
|
||||
load = (usbif_be_driver_status_changed_t *)msg->msg;
|
||||
debug_begin("USBIF_BE", "DRIVER_STATUS_CHANGED");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_BE", "DRIVER_STATUS_CHANGED");
|
||||
} else {
|
||||
debug_begin("USBIF_BE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("USBIF_BE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
case CMSG_USBIF_FE:
|
||||
if (msg->subtype == CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED) {
|
||||
usbif_fe_interface_status_changed_t *load;
|
||||
load = (usbif_fe_interface_status_changed_t *)msg->msg;
|
||||
debug_begin("USBIF_FE", "INTERFACE_STATUS_CHANGED");
|
||||
debug_field(load, status, "%u");
|
||||
debug_field(load, evtchn, "%u");
|
||||
debug_field(load, domid, "%u");
|
||||
debug_field(load, bandwidth, "%u");
|
||||
debug_field(load, num_ports, "%u");
|
||||
debug_end("USBIF_FE", "INTERFACE_STATUS_CHANGED");
|
||||
} else if (msg->subtype == CMSG_USBIF_FE_DRIVER_STATUS_CHANGED) {
|
||||
usbif_fe_driver_status_changed_t *load;
|
||||
load = (usbif_fe_driver_status_changed_t *)msg->msg;
|
||||
debug_begin("USBIF_FE", "DRIVER_STATUS_CHANGED");
|
||||
debug_field(load, status, "%u");
|
||||
debug_end("USBIF_FE", "DRIVER_STATUS_CHANGED");
|
||||
} else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_CONNECT) {
|
||||
usbif_fe_interface_connect_t *load;
|
||||
load = (usbif_fe_interface_connect_t *)msg->msg;
|
||||
debug_begin("USBIF_FE", "INTERFACE_CONNECT");
|
||||
debug_field(load, shmem_frame, "%lu");
|
||||
debug_end("USBIF_FE", "INTERFACE_CONNECT");
|
||||
} else if (msg->subtype == CMSG_USBIF_FE_INTERFACE_DISCONNECT) {
|
||||
debug_begin("USBIF_FE", "INTERFACE_DISCONNECT");
|
||||
debug_end("USBIF_FE", "INTERFACE_DISCONNECT");
|
||||
} else {
|
||||
debug_begin("USBIF_FE", "UNKNOWN");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("USBIF_FE", "UNKNOWN");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug_begin("UNKNOWN", "UNKNOWN");
|
||||
debug_field(msg, type, "%u");
|
||||
debug_field(msg, subtype, "%u");
|
||||
debug_field(msg, length, "%u");
|
||||
debug_dump(msg, msg, length);
|
||||
debug_end("UNKNOWN", "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s\n", buffer);
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#ifndef XENCTLD_ERROR_H
|
||||
#define XENCTLD_ERROR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
|
||||
void dump_msg(const control_msg_t *msg, uint64_t flags);
|
||||
|
||||
#endif
|
||||
@@ -1,106 +0,0 @@
|
||||
/* evtchn.c
|
||||
*
|
||||
* Interfaces to event channel driver.
|
||||
*
|
||||
* Most of this is directly based on the original xu interface to python
|
||||
* written by Keir Fraser.
|
||||
*
|
||||
* (c) 2004, Andrew Warfield
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h> /* XOPEN drops makedev, this gets it back. */
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "xcs.h"
|
||||
|
||||
static int evtchn_fd = -1;
|
||||
|
||||
/* NB. The following should be kept in sync with the kernel's evtchn driver. */
|
||||
#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
|
||||
#define EVTCHN_DEV_MAJOR 10
|
||||
#define EVTCHN_DEV_MINOR 201
|
||||
/* /dev/xen/evtchn ioctls: */
|
||||
/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
|
||||
#define EVTCHN_RESET _IO('E', 1)
|
||||
/* EVTCHN_BIND: Bind to teh specified event-channel port. */
|
||||
#define EVTCHN_BIND _IO('E', 2)
|
||||
/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
|
||||
#define EVTCHN_UNBIND _IO('E', 3)
|
||||
|
||||
int evtchn_read()
|
||||
{
|
||||
u16 v;
|
||||
int bytes;
|
||||
|
||||
while ( (bytes = read(evtchn_fd, &v, sizeof(v))) == -1 )
|
||||
{
|
||||
if ( errno == EINTR )
|
||||
continue;
|
||||
/* EAGAIN was cased to return 'None' in the python version... */
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if ( bytes == sizeof(v) )
|
||||
return v;
|
||||
|
||||
/* bad return */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void evtchn_unmask(u16 idx)
|
||||
{
|
||||
(void)write(evtchn_fd, &idx, sizeof(idx));
|
||||
}
|
||||
|
||||
int evtchn_bind(int idx)
|
||||
{
|
||||
if ( ioctl(evtchn_fd, EVTCHN_BIND, idx) != 0 )
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int evtchn_unbind(int idx)
|
||||
{
|
||||
if ( ioctl(evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int evtchn_open(void)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* 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:
|
||||
evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
|
||||
if ( 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;
|
||||
return -errno;
|
||||
}
|
||||
return evtchn_fd;
|
||||
}
|
||||
|
||||
void evtchn_close()
|
||||
{
|
||||
(void)close(evtchn_fd);
|
||||
evtchn_fd = -1;
|
||||
}
|
||||
|
||||
-973
@@ -1,973 +0,0 @@
|
||||
/* xcs.c
|
||||
*
|
||||
* xcs - Xen Control Switch
|
||||
*
|
||||
* Copyright (c) 2004, Andrew Warfield
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Things we need to select on in xcs:
|
||||
|
||||
1. Events arriving on /dev/evtchn
|
||||
|
||||
These will kick a function to read everything off the fd, and scan the
|
||||
associated control message rings, resulting in notifications sent on
|
||||
data channels to connected clients.
|
||||
|
||||
2. New TCP connections on XCS_PORT.
|
||||
|
||||
These will either be control (intially) or associated data connections.
|
||||
|
||||
Control connections will instantiate or rebind to an existing connnection
|
||||
struct. The control channel is used to configure what events will be
|
||||
received on an associated data channel. These two channels are split
|
||||
out because the control channel is synchronous, all messages will return
|
||||
a result from XCS. The data channel is effectively asynchronous, events
|
||||
may arrive in the middle of a control message exchange. Additionally,
|
||||
Having two TCP connections allows the client side to have a blocking
|
||||
listen loop for data messages, while independently interacting on the
|
||||
control channel at other places in the code.
|
||||
|
||||
Data connections attach to an existing control struct, using a session
|
||||
id that is passed during the control connect. There is currently a
|
||||
one-to-one relationship between data and control channels, but there
|
||||
could just as easily be many data channels, if there were a set of
|
||||
clients with identical interests, or if you wanted to trace an existing
|
||||
client's data traffic.
|
||||
|
||||
3. Messages arriving on open TCP connections.
|
||||
There are three types of open connections:
|
||||
|
||||
3a. Messages arriving on open control channel file descriptors.
|
||||
|
||||
[description of the control protocol here]
|
||||
|
||||
3b. Messages arriving on open data channel file descriptors.
|
||||
|
||||
[description of the data protocol here]
|
||||
|
||||
3c. Messages arriving on (new) unbound connections.
|
||||
|
||||
A connection must issue a XCS_CONNECT message to specify what
|
||||
it is, after which the connection is moved into one of the above
|
||||
two groups.
|
||||
|
||||
Additionally, we need a periodic timer to do housekeeping.
|
||||
|
||||
4. Every XCS_GC_INTERVAL seconds, we need to clean up outstanding state.
|
||||
Specifically, we garbage collect any sessions (connection_t structs)
|
||||
that have been unconnected for a period of time (XCS_SESSION_TIMEOUT),
|
||||
and close any connections that have been openned, but not connected
|
||||
as a control or data connection (XCS_UFD_TIMEOUT).
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include "xcs.h"
|
||||
|
||||
#undef fd_max
|
||||
#define fd_max(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
/* ------[ Control channel interfaces ]------------------------------------*/
|
||||
|
||||
static control_channel_t *cc_list[NR_EVENT_CHANNELS];
|
||||
static int *dom_port_map = 0;
|
||||
static int dom_port_map_size = 0;
|
||||
|
||||
static void map_dom_to_port(u32 dom, int port)
|
||||
{
|
||||
if (dom >= dom_port_map_size) {
|
||||
dom_port_map = (int *)realloc(dom_port_map,
|
||||
(dom + 256) * sizeof(dom_port_map[0]));
|
||||
|
||||
if (dom_port_map == NULL) {
|
||||
perror("realloc(dom_port_map)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (; dom_port_map_size < dom + 256; dom_port_map_size++) {
|
||||
dom_port_map[dom_port_map_size] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
dom_port_map[dom] = port;
|
||||
}
|
||||
|
||||
static int dom_to_port(u32 dom)
|
||||
{
|
||||
if (dom >= dom_port_map_size) return -1;
|
||||
|
||||
return dom_port_map[dom];
|
||||
}
|
||||
|
||||
static void init_interfaces(void)
|
||||
{
|
||||
memset(cc_list, 0, sizeof cc_list);
|
||||
}
|
||||
|
||||
static control_channel_t *add_interface(u32 dom, int local_port,
|
||||
int remote_port)
|
||||
{
|
||||
control_channel_t *cc=NULL, *oldcc;
|
||||
int ret;
|
||||
|
||||
if ((dom_to_port(dom) >= 0) && (cc_list[dom_to_port(dom)] != NULL))
|
||||
{
|
||||
return(cc_list[dom_to_port(dom)]);
|
||||
}
|
||||
|
||||
if (cc_list[local_port] == NULL)
|
||||
{
|
||||
cc = ctrl_chan_new(dom, local_port, remote_port);
|
||||
}
|
||||
|
||||
if (cc == NULL)
|
||||
return NULL;
|
||||
|
||||
DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
|
||||
dom, local_port, remote_port, cc);
|
||||
DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
|
||||
dom, cc->local_port, cc->remote_port, cc);
|
||||
|
||||
if ((ret = evtchn_bind(cc->local_port)) != 0)
|
||||
{
|
||||
DPRINTF("Got control interface, but couldn't bind evtchan!(%d)\n", ret);
|
||||
ctrl_chan_free(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( cc_list[cc->local_port] != NULL )
|
||||
{
|
||||
oldcc = cc_list[cc->local_port];
|
||||
|
||||
if ((oldcc->remote_dom != cc->remote_dom) ||
|
||||
(oldcc->remote_port != cc->remote_port))
|
||||
{
|
||||
DPRINTF("CC conflict! (port: %d, old dom: %u, new dom: %u, "
|
||||
"old ref_count: %d)\n",
|
||||
cc->local_port, oldcc->remote_dom, cc->remote_dom,
|
||||
oldcc->ref_count);
|
||||
map_dom_to_port(oldcc->remote_dom, -1);
|
||||
ctrl_chan_free(cc_list[cc->local_port]);
|
||||
cc_list[cc->local_port] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cc_list[cc->local_port] = cc;
|
||||
map_dom_to_port(cc->remote_dom, cc->local_port);
|
||||
cc->type = CC_TYPE_INTERDOMAIN;
|
||||
cc->ref_count = 0;
|
||||
return cc;
|
||||
}
|
||||
|
||||
control_channel_t *add_virq(int virq)
|
||||
{
|
||||
control_channel_t *cc;
|
||||
int virq_port;
|
||||
|
||||
if (ctrl_chan_bind_virq(virq, &virq_port) == -1)
|
||||
return NULL;
|
||||
|
||||
if ((cc_list[virq_port] != NULL) &&
|
||||
(cc_list[virq_port]->type != CC_TYPE_VIRQ))
|
||||
return NULL;
|
||||
|
||||
if ((cc_list[virq_port] != NULL) &&
|
||||
(cc_list[virq_port]->type == CC_TYPE_VIRQ))
|
||||
return cc_list[virq_port];
|
||||
|
||||
cc = (control_channel_t *)malloc(sizeof(control_channel_t));
|
||||
if ( cc == NULL ) return NULL;
|
||||
|
||||
memset(cc, 0, sizeof(control_channel_t));
|
||||
cc->type = CC_TYPE_VIRQ;
|
||||
cc->local_port = virq_port;
|
||||
cc->virq = virq;
|
||||
cc->ref_count = 1;
|
||||
|
||||
if (evtchn_bind(cc->local_port) != 0)
|
||||
{
|
||||
DPRINTF("Got control interface, but couldn't bind evtchan!\n");
|
||||
free(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cc_list[cc->local_port] = cc;
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
void get_interface(control_channel_t *cc)
|
||||
{
|
||||
if (cc != NULL)
|
||||
cc->ref_count++;
|
||||
}
|
||||
|
||||
void put_interface(control_channel_t *cc)
|
||||
{
|
||||
if (cc != NULL)
|
||||
{
|
||||
cc->ref_count--;
|
||||
if (cc->ref_count <= 0)
|
||||
{
|
||||
DPRINTF("Freeing cc on port %d.\n", cc->local_port);
|
||||
(void)evtchn_unbind(cc->local_port);
|
||||
cc_list[cc->local_port] = NULL;
|
||||
map_dom_to_port(cc->remote_dom, -1);
|
||||
ctrl_chan_free(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------[ Simple helpers ]------------------------------------------------*/
|
||||
|
||||
/* listen_socket() is straight from paul sheer's useful select_tut manpage. */
|
||||
static int listen_socket (char *listen_path)
|
||||
{
|
||||
struct sockaddr_un a;
|
||||
int s;
|
||||
int yes;
|
||||
|
||||
if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
perror ("socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
yes = 1;
|
||||
|
||||
memset (&a, 0, sizeof (a));
|
||||
a.sun_family = AF_UNIX;
|
||||
strcpy(a.sun_path, listen_path);
|
||||
|
||||
/* remove an old socket if it exists. */
|
||||
unlink(listen_path);
|
||||
|
||||
if (bind(s, (struct sockaddr *) &a, sizeof (a)) < 0)
|
||||
{
|
||||
fprintf (stderr, "bind('%s'): %s\n", listen_path, strerror(errno));
|
||||
close (s);
|
||||
return -1;
|
||||
}
|
||||
DPRINTF ("accepting connections on path %s\n", listen_path);
|
||||
listen (s, 10);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ------[ Message handlers ]----------------------------------------------*/
|
||||
|
||||
#define NO_CHANGE 0
|
||||
#define CONNECTED 1
|
||||
#define DISCONNECTED 2
|
||||
int handle_connect_msg( xcs_msg_t *msg, int fd )
|
||||
{
|
||||
xcs_connect_msg_t *cmsg = &msg->u.connect;
|
||||
connection_t *con;
|
||||
int ret = NO_CHANGE;
|
||||
|
||||
switch (msg->type)
|
||||
{
|
||||
case XCS_CONNECT_CTRL:
|
||||
{
|
||||
if ( cmsg->session_id == 0 )
|
||||
{
|
||||
con = connection_new();
|
||||
if ( con == NULL)
|
||||
{
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
break;
|
||||
}
|
||||
msg->result = XCS_RSLT_OK;
|
||||
cmsg->session_id = con->id;
|
||||
con->ctrl_fd = fd;
|
||||
ret = CONNECTED;
|
||||
DPRINTF("New control connection\n");
|
||||
break;
|
||||
}
|
||||
|
||||
con = get_con_by_session(cmsg->session_id);
|
||||
if ( con == NULL )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADSESSION;
|
||||
break;
|
||||
}
|
||||
if ( con->ctrl_fd != -1 )
|
||||
{
|
||||
msg->result = XCS_RSLT_CONINUSE;
|
||||
break;
|
||||
}
|
||||
con->ctrl_fd = fd;
|
||||
msg->result = XCS_RSLT_OK;
|
||||
ret = CONNECTED;
|
||||
DPRINTF("Rebound to control connection\n");
|
||||
break;
|
||||
}
|
||||
case XCS_CONNECT_DATA:
|
||||
{
|
||||
con = get_con_by_session(cmsg->session_id);
|
||||
if ( con == NULL )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADSESSION;
|
||||
break;
|
||||
}
|
||||
if ( con->data_fd != -1 )
|
||||
{
|
||||
msg->result = XCS_RSLT_CONINUSE;
|
||||
break;
|
||||
}
|
||||
con->data_fd = fd;
|
||||
msg->result = XCS_RSLT_OK;
|
||||
ret = CONNECTED;
|
||||
DPRINTF("Attached data connection\n");
|
||||
break;
|
||||
|
||||
}
|
||||
case XCS_CONNECT_BYE:
|
||||
{
|
||||
close ( fd );
|
||||
ret = DISCONNECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_control_message( connection_t *con, xcs_msg_t *msg )
|
||||
{
|
||||
int ret;
|
||||
int reply_needed = 1;
|
||||
|
||||
DPRINTF("Got message, type %u.\n", msg->type);
|
||||
|
||||
switch (msg->type)
|
||||
{
|
||||
case XCS_MSG_BIND:
|
||||
{
|
||||
xcs_bind_msg_t *bmsg = &msg->u.bind;
|
||||
|
||||
if ( ! BIND_MSG_VALID(bmsg) )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADREQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xcs_bind(con, bmsg->port, bmsg->type);
|
||||
if (ret == 0) {
|
||||
msg->result = XCS_RSLT_OK;
|
||||
} else {
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCS_MSG_UNBIND:
|
||||
{
|
||||
xcs_bind_msg_t *bmsg = &msg->u.bind;
|
||||
|
||||
if ( ! BIND_MSG_VALID(bmsg) )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADREQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xcs_unbind(con, bmsg->port, bmsg->type);
|
||||
if (ret == 0) {
|
||||
msg->result = XCS_RSLT_OK;
|
||||
} else {
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCS_VIRQ_BIND:
|
||||
{
|
||||
control_channel_t *cc;
|
||||
xcs_virq_msg_t *vmsg = &msg->u.virq;
|
||||
if ( ! VIRQ_MSG_VALID(vmsg) )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADREQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
cc = add_virq(vmsg->virq);
|
||||
if (cc == NULL)
|
||||
{
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
break;
|
||||
}
|
||||
ret = xcs_bind(con, cc->local_port, TYPE_VIRQ);
|
||||
if (ret == 0) {
|
||||
vmsg->port = cc->local_port;
|
||||
msg->result = XCS_RSLT_OK;
|
||||
} else {
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XCS_CIF_NEW_CC:
|
||||
{
|
||||
control_channel_t *cc;
|
||||
xcs_interface_msg_t *imsg = &msg->u.interface;
|
||||
|
||||
if ( ! INTERFACE_MSG_VALID(imsg) )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADREQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
|
||||
if (cc != NULL) {
|
||||
get_interface(cc);
|
||||
msg->result = XCS_RSLT_OK;
|
||||
imsg->local_port = cc->local_port;
|
||||
imsg->remote_port = cc->remote_port;
|
||||
} else {
|
||||
msg->result = XCS_RSLT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XCS_CIF_FREE_CC:
|
||||
{
|
||||
control_channel_t *cc;
|
||||
xcs_interface_msg_t *imsg = &msg->u.interface;
|
||||
|
||||
if ( ! INTERFACE_MSG_VALID(imsg) )
|
||||
{
|
||||
msg->result = XCS_RSLT_BADREQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
|
||||
if (cc != NULL) {
|
||||
put_interface(cc);
|
||||
}
|
||||
msg->result = XCS_RSLT_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return reply_needed;
|
||||
}
|
||||
|
||||
void handle_data_message( connection_t *con, xcs_msg_t *msg )
|
||||
{
|
||||
control_channel_t *cc;
|
||||
xcs_control_msg_t *cmsg = &msg->u.control;
|
||||
int port;
|
||||
|
||||
switch (msg->type)
|
||||
{
|
||||
case XCS_REQUEST:
|
||||
if ( cmsg->remote_dom > MAX_DOMS )
|
||||
break;
|
||||
|
||||
port = dom_to_port(cmsg->remote_dom);
|
||||
if (port == -1) break;
|
||||
cc = cc_list[port];
|
||||
if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
|
||||
{
|
||||
DPRINTF("DN:REQ: dom:%d port: %d type: %d\n",
|
||||
cc->remote_dom, cc->local_port,
|
||||
cmsg->msg.type);
|
||||
ctrl_chan_write_request(cc, cmsg);
|
||||
ctrl_chan_notify(cc);
|
||||
} else {
|
||||
DPRINTF("tried to send a REQ to a null cc\n.");
|
||||
}
|
||||
break;
|
||||
|
||||
case XCS_RESPONSE:
|
||||
if ( cmsg->remote_dom > MAX_DOMS )
|
||||
break;
|
||||
|
||||
port = dom_to_port(cmsg->remote_dom);
|
||||
if (port == -1) break;
|
||||
cc = cc_list[port];
|
||||
if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
|
||||
{
|
||||
DPRINTF("DN:RSP: dom:%d port: %d type: %d\n",
|
||||
cc->remote_dom, cc->local_port,
|
||||
cmsg->msg.type);
|
||||
ctrl_chan_write_response(cc, cmsg);
|
||||
ctrl_chan_notify(cc);
|
||||
}
|
||||
break;
|
||||
|
||||
case XCS_VIRQ:
|
||||
if ( !(PORT_VALID(cmsg->local_port)) )
|
||||
break;
|
||||
|
||||
cc = cc_list[cmsg->local_port];
|
||||
|
||||
if ((cc != NULL) && ( cc->type == CC_TYPE_VIRQ ))
|
||||
{
|
||||
DPRINTF("DN:VIRQ: virq: %d port: %d\n",
|
||||
cc->virq, cc->local_port);
|
||||
ctrl_chan_notify(cc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------[ Control interface handler ]-------------------------------------*/
|
||||
|
||||
/* passed as a function pointer to the lookup. */
|
||||
void send_kmsg(connection_t *c, void *arg)
|
||||
{
|
||||
xcs_msg_t *msg = (xcs_msg_t *)arg;
|
||||
|
||||
DPRINTF(" -> CONNECTION %d\n", c->data_fd);
|
||||
if (c->data_fd > 0)
|
||||
{
|
||||
send(c->data_fd, msg, sizeof(xcs_msg_t), 0);
|
||||
}
|
||||
}
|
||||
|
||||
int handle_ctrl_if(void)
|
||||
{
|
||||
control_channel_t *cc;
|
||||
control_msg_t *msg;
|
||||
xcs_msg_t kmsg;
|
||||
int chan, ret;
|
||||
|
||||
DPRINTF("Event thread kicked!\n");
|
||||
again:
|
||||
while ((chan = evtchn_read()) > 0)
|
||||
{
|
||||
evtchn_unmask(chan);
|
||||
cc = cc_list[chan];
|
||||
if (cc_list[chan] == NULL) {
|
||||
DPRINTF("event from unknown channel (%d)\n", chan);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( cc_list[chan]->type == CC_TYPE_VIRQ )
|
||||
{
|
||||
DPRINTF("UP:VIRQ: virq:%d port: %d\n",
|
||||
cc->virq, cc->local_port);
|
||||
kmsg.type = XCS_VIRQ;
|
||||
kmsg.u.control.local_port = cc->local_port;
|
||||
xcs_lookup(cc->local_port, TYPE_VIRQ, send_kmsg, &kmsg);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (ctrl_chan_request_to_read(cc))
|
||||
{
|
||||
msg = &kmsg.u.control.msg;
|
||||
kmsg.type = XCS_REQUEST;
|
||||
kmsg.u.control.remote_dom = cc->remote_dom;
|
||||
kmsg.u.control.local_port = cc->local_port;
|
||||
ret = ctrl_chan_read_request(cc, &kmsg.u.control);
|
||||
DPRINTF("UP:REQ: dom:%d port: %d type: %d len: %d\n",
|
||||
cc->remote_dom, cc->local_port,
|
||||
msg->type, msg->length);
|
||||
if (ret == 0)
|
||||
xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
|
||||
}
|
||||
|
||||
while (ctrl_chan_response_to_read(cc))
|
||||
{
|
||||
msg = &kmsg.u.control.msg;
|
||||
kmsg.type = XCS_RESPONSE;
|
||||
kmsg.u.control.remote_dom = cc->remote_dom;
|
||||
kmsg.u.control.local_port = cc->local_port;
|
||||
ret = ctrl_chan_read_response(cc, &kmsg.u.control);
|
||||
DPRINTF("UP:RSP: dom:%d port: %d type: %d len: %d\n",
|
||||
cc->remote_dom, cc->local_port,
|
||||
msg->type, msg->length);
|
||||
if (ret == 0)
|
||||
xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
|
||||
}
|
||||
}
|
||||
|
||||
if (chan == -EINTR)
|
||||
goto again;
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
/* ------[ Main xcs code / big select loop ]-------------------------------*/
|
||||
|
||||
|
||||
typedef struct unbound_fd_st {
|
||||
int fd;
|
||||
struct timeval born;
|
||||
struct unbound_fd_st *next;
|
||||
} unbound_fd_t;
|
||||
|
||||
/* This makes ufd point to the next entry in the list, so need to *
|
||||
* break/continue if called while iterating. */
|
||||
void delete_ufd(unbound_fd_t **ufd)
|
||||
{
|
||||
unbound_fd_t *del_ufd;
|
||||
|
||||
del_ufd = *ufd;
|
||||
*ufd = (*ufd)->next;
|
||||
free( del_ufd );
|
||||
}
|
||||
|
||||
void gc_ufd_list( unbound_fd_t **ufd )
|
||||
{
|
||||
struct timeval now, delta;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
while ( *ufd != NULL )
|
||||
{
|
||||
timersub(&now, &(*ufd)->born, &delta);
|
||||
if (delta.tv_sec > XCS_UFD_TIMEOUT)
|
||||
{
|
||||
DPRINTF("GC-UFD: closing fd: %d\n", (*ufd)->fd);
|
||||
close((*ufd)->fd);
|
||||
delete_ufd(ufd);
|
||||
continue;
|
||||
}
|
||||
ufd = &(*ufd)->next;
|
||||
}
|
||||
}
|
||||
|
||||
void daemonize_xcs(void)
|
||||
{
|
||||
|
||||
/* detach from our controlling tty so that a shell does hang waiting for
|
||||
stopped jobs. */
|
||||
|
||||
pid_t pid = fork();
|
||||
int fd;
|
||||
|
||||
if (pid == -1) {
|
||||
perror("fork()");
|
||||
} else if (pid) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fd = open("/var/log/xcs.log", O_WRONLY | O_APPEND | O_CREAT);
|
||||
if ( fd == -1 ) {
|
||||
fprintf(stderr, "xcs couldn't open logfile. Directing all output to "
|
||||
"/dev/null instead.\n");
|
||||
fd = open("/dev/null", O_WRONLY);
|
||||
}
|
||||
|
||||
setsid();
|
||||
close(2);
|
||||
close(1);
|
||||
close(0);
|
||||
dup(fd);
|
||||
dup(fd);
|
||||
}
|
||||
|
||||
|
||||
static char *pidfilename = NULL;
|
||||
void cleanup(int sig)
|
||||
{
|
||||
/* throw away our pidfile if we created one. */
|
||||
if ( pidfilename != NULL )
|
||||
unlink(pidfilename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int listen_fd, evtchn_fd;
|
||||
unbound_fd_t *unbound_fd_list = NULL, **ufd;
|
||||
struct timeval timeout = { XCS_GC_INTERVAL, 0 };
|
||||
connection_t **con;
|
||||
int c, daemonize;
|
||||
FILE *pidfile;
|
||||
struct stat s;
|
||||
|
||||
daemonize = 1;
|
||||
pidfile = NULL;
|
||||
|
||||
signal(SIGHUP, cleanup);
|
||||
signal(SIGTERM, cleanup);
|
||||
signal(SIGINT, cleanup);
|
||||
|
||||
/* Do a bunch of stuff before potentially daemonizing so we can
|
||||
* print error messages sanely before redirecting output. */
|
||||
|
||||
/* Initialize xc and event connections. */
|
||||
if (ctrl_chan_init() != 0)
|
||||
{
|
||||
printf("Couldn't open conneciton to libxc.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((evtchn_fd = evtchn_open()) < 0)
|
||||
{
|
||||
printf("Couldn't open event channel driver interface.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Bind listen_fd to the client socket. */
|
||||
listen_fd = listen_socket(XCS_SUN_PATH);
|
||||
|
||||
while ((c = getopt (argc, argv, "ip:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'i': /* interactive */
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'p': /* pid file */
|
||||
pidfilename = optarg;
|
||||
break;
|
||||
case '?':
|
||||
if (isprint (optopt))
|
||||
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
|
||||
else
|
||||
fprintf (stderr,
|
||||
"Bad option character `\\x%x'.\n", optopt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pidfilename != NULL )
|
||||
{
|
||||
if ( stat(pidfilename, &s) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Thre specified pid file (%s) already exists.\n"
|
||||
"Is another instance of xcs running?\n", pidfilename);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
pidfile = fopen(pidfilename, "w");
|
||||
if (pidfile == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error openning pidfile (%s).\n", pidfilename);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize == 1)
|
||||
daemonize_xcs();
|
||||
|
||||
if (pidfile != NULL)
|
||||
{
|
||||
fprintf(pidfile, "%d", getpid());
|
||||
fclose(pidfile);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize control interfaces, bindings. */
|
||||
init_interfaces();
|
||||
init_bindings();
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int n = 0, ret;
|
||||
fd_set rd, wr, er;
|
||||
FD_ZERO ( &rd );
|
||||
FD_ZERO ( &wr );
|
||||
FD_ZERO ( &er );
|
||||
|
||||
/* TCP listen fd: */
|
||||
FD_SET ( listen_fd, &rd );
|
||||
n = fd_max ( n, listen_fd );
|
||||
|
||||
/* Evtchn fd: */
|
||||
FD_SET ( evtchn_fd, &rd );
|
||||
n = fd_max ( n, evtchn_fd );
|
||||
|
||||
/* unbound connection fds: */
|
||||
ufd = &unbound_fd_list;
|
||||
while ((*ufd) != NULL)
|
||||
{
|
||||
FD_SET ( (*ufd)->fd, &rd );
|
||||
n = fd_max ( n, (*ufd)->fd );
|
||||
ufd = &(*ufd)->next;
|
||||
}
|
||||
|
||||
/* control and data fds: */
|
||||
con = &connection_list;
|
||||
while ((*con) != NULL)
|
||||
{
|
||||
if ((*con)->ctrl_fd > 0)
|
||||
{
|
||||
FD_SET ( (*con)->ctrl_fd, &rd );
|
||||
n = fd_max ( n, (*con)->ctrl_fd );
|
||||
}
|
||||
if ((*con)->data_fd > 0)
|
||||
{
|
||||
FD_SET ( (*con)->data_fd, &rd );
|
||||
n = fd_max ( n, (*con)->data_fd );
|
||||
}
|
||||
con = &(*con)->next;
|
||||
}
|
||||
|
||||
ret = select ( n + 1, &rd, &wr, &er, &timeout );
|
||||
|
||||
if ( (timeout.tv_sec == 0) && (timeout.tv_usec == 0) )
|
||||
{
|
||||
gc_ufd_list(&unbound_fd_list);
|
||||
gc_connection_list();
|
||||
timeout.tv_sec = XCS_GC_INTERVAL;
|
||||
}
|
||||
|
||||
if ( (ret == -1) && (errno == EINTR) )
|
||||
continue;
|
||||
if ( ret < 0 )
|
||||
{
|
||||
perror ("select()");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* CASE 1: Events arriving on /dev/evtchn. */
|
||||
|
||||
if ( FD_ISSET (evtchn_fd, &rd ))
|
||||
handle_ctrl_if();
|
||||
|
||||
/* CASE 2: New connection on the listen port. */
|
||||
if ( FD_ISSET ( listen_fd, &rd ))
|
||||
{
|
||||
struct sockaddr_un remote_addr;
|
||||
int size;
|
||||
memset (&remote_addr, 0, sizeof (remote_addr));
|
||||
size = sizeof remote_addr;
|
||||
ret = accept(listen_fd, (struct sockaddr *)&remote_addr, (socklen_t *)&size);
|
||||
if ( ret < 0 )
|
||||
{
|
||||
perror("accept()");
|
||||
} else {
|
||||
unbound_fd_t *new_ufd;
|
||||
|
||||
new_ufd = (unbound_fd_t *)malloc(sizeof(*new_ufd));
|
||||
|
||||
if (new_ufd != NULL)
|
||||
{
|
||||
gettimeofday(&new_ufd->born, NULL);
|
||||
new_ufd->fd = ret;
|
||||
new_ufd->next = unbound_fd_list;
|
||||
unbound_fd_list = new_ufd;
|
||||
} else {
|
||||
perror("malloc unbound connection");
|
||||
close(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CASE 3a: Handle messages on control connections. */
|
||||
|
||||
con = &connection_list;
|
||||
while ( *con != NULL )
|
||||
{
|
||||
if ( ((*con)->ctrl_fd > 0) && (FD_ISSET((*con)->ctrl_fd, &rd)) )
|
||||
{
|
||||
xcs_msg_t msg;
|
||||
memset (&msg, 0, sizeof(msg));
|
||||
ret = read( (*con)->ctrl_fd, &msg, sizeof(msg) );
|
||||
|
||||
if ( ret < 0 )
|
||||
{
|
||||
perror("reading ctrl fd.");
|
||||
} else if ( ret == 0 )
|
||||
{
|
||||
DPRINTF("Control connection dropped.\n");
|
||||
close ( (*con)->ctrl_fd );
|
||||
(*con)->ctrl_fd = -1;
|
||||
gettimeofday(&(*con)->disconnect_time, NULL);
|
||||
} else
|
||||
{
|
||||
if ( ret != sizeof(msg) )
|
||||
{
|
||||
DPRINTF("Unexpected frame size!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = handle_control_message( *con, &msg );
|
||||
|
||||
if ( ret == 1 )
|
||||
send( (*con)->ctrl_fd, &msg, sizeof(msg), 0 );
|
||||
}
|
||||
}
|
||||
con = &(*con)->next;
|
||||
}
|
||||
|
||||
/* CASE 3b: Handle messages on data connections. */
|
||||
|
||||
con = &connection_list;
|
||||
while ( *con != NULL )
|
||||
{
|
||||
if ( ((*con)->data_fd > 0) && (FD_ISSET((*con)->data_fd, &rd)) )
|
||||
{
|
||||
xcs_msg_t msg;
|
||||
memset (&msg, 0, sizeof(msg));
|
||||
ret = read( (*con)->data_fd, &msg, sizeof(msg) );
|
||||
|
||||
if ( ret < 0 )
|
||||
{
|
||||
perror("reading data fd.");
|
||||
} else if ( ret == 0 )
|
||||
{
|
||||
DPRINTF("Data connection dropped.\n");
|
||||
close ( (*con)->data_fd );
|
||||
(*con)->data_fd = -1;
|
||||
gettimeofday(&(*con)->disconnect_time, NULL);
|
||||
} else
|
||||
{
|
||||
if ( ret != sizeof(msg) )
|
||||
{
|
||||
DPRINTF("Unexpected frame size!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
handle_data_message( *con, &msg );
|
||||
}
|
||||
}
|
||||
con = &(*con)->next;
|
||||
}
|
||||
|
||||
/* CASE 3c: Handle messages arriving on unbound connections. */
|
||||
ufd = &unbound_fd_list;
|
||||
while ((*ufd) != NULL)
|
||||
{
|
||||
if ( FD_ISSET( (*ufd)->fd, &rd ) )
|
||||
{
|
||||
xcs_msg_t msg;
|
||||
memset (&msg, 0, sizeof(msg));
|
||||
ret = read( (*ufd)->fd, &msg, sizeof(msg) );
|
||||
|
||||
if ( ret == 0 )
|
||||
{
|
||||
close ( (*ufd)->fd );
|
||||
delete_ufd(ufd);
|
||||
continue; /* we just advanced ufd */
|
||||
} else {
|
||||
if ( ret != sizeof(msg) )
|
||||
{
|
||||
DPRINTF("Unexpected frame size!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = handle_connect_msg( &msg, (*ufd)->fd );
|
||||
|
||||
if ( (ret == CONNECTED) || (ret == NO_CHANGE) )
|
||||
send( (*ufd)->fd, &msg, sizeof(msg), 0 );
|
||||
|
||||
if ( (ret = CONNECTED) || (ret = DISCONNECTED) )
|
||||
{
|
||||
delete_ufd( ufd );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
ufd = &(*ufd)->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
/* xcs.h
|
||||
*
|
||||
* public interfaces for the control interface switch (xcs).
|
||||
*
|
||||
* (c) 2004, Andrew Warfield
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __XCS_H__
|
||||
#define __XCS_H__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <xen/linux/privcmd.h>
|
||||
#include <sys/time.h>
|
||||
#include "xcs_proto.h"
|
||||
|
||||
/* ------[ Debug macros ]--------------------------------------------------*/
|
||||
|
||||
#if 0
|
||||
#define DPRINTF(_f, _a...) printf ( _f , ## _a )
|
||||
#else
|
||||
#define DPRINTF(_f, _a...) ((void)0)
|
||||
#endif
|
||||
|
||||
/* ------[ XCS-specific defines and types ]--------------------------------*/
|
||||
|
||||
#define MAX_DOMS 1024
|
||||
#define XCS_SESSION_TIMEOUT 10 /* (secs) disconnected session gc timeout */
|
||||
#define XCS_UFD_TIMEOUT 5 /* how long can connections be unbound? */
|
||||
#define XCS_GC_INTERVAL 5 /* How often to run gc handlers. */
|
||||
|
||||
|
||||
/* ------[ Other required defines ]----------------------------------------*/
|
||||
|
||||
/* Size of a machine page frame. */
|
||||
#define PAGE_SIZE XC_PAGE_SIZE
|
||||
|
||||
#ifndef timersub /* XOPEN and __BSD don't cooperate well... */
|
||||
#define timersub(a, b, result) \
|
||||
do { \
|
||||
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
||||
if ((result)->tv_usec < 0) { \
|
||||
--(result)->tv_sec; \
|
||||
(result)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /*timersub*/
|
||||
|
||||
/* ------[ Bindings Interface ]--------------------------------------------*/
|
||||
|
||||
/*forward declare connection_t */
|
||||
typedef struct connection_st connection_t;
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
u16 type;
|
||||
} binding_key_t;
|
||||
|
||||
typedef struct binding_key_ent_st {
|
||||
binding_key_t key;
|
||||
struct binding_key_ent_st *next;
|
||||
} binding_key_ent_t;
|
||||
|
||||
#define BINDING_KEYS_EQUAL(_k1, _k2) \
|
||||
(((_k1)->port == (_k2)->port) && ((_k1)->type == (_k2)->type))
|
||||
|
||||
int xcs_bind(connection_t *con, int port, u16 type);
|
||||
int xcs_unbind(connection_t *con, int port, u16 type);
|
||||
void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *),
|
||||
void *arg);
|
||||
void init_bindings(void);
|
||||
|
||||
/* ------[ Connection Interface ]------------------------------------------*/
|
||||
|
||||
struct connection_st {
|
||||
unsigned long id; /* Unique session id */
|
||||
int ctrl_fd; /* TCP descriptors */
|
||||
int data_fd; /* */
|
||||
binding_key_ent_t *bindings; /* List of bindings */
|
||||
connection_t *next; /* Linked list of connections */
|
||||
struct timeval disconnect_time; /* " " */
|
||||
}; /* previously typedefed as connection_t */
|
||||
|
||||
|
||||
extern connection_t *connection_list;
|
||||
|
||||
connection_t *get_con_by_session(unsigned long session_id);
|
||||
connection_t *connection_new();
|
||||
void connection_free(connection_t *con);
|
||||
int connection_add_binding(connection_t *con, binding_key_t *key);
|
||||
int connection_remove_binding(connection_t *con, binding_key_t *key);
|
||||
int connection_has_binding(connection_t *con, binding_key_t *key);
|
||||
void gc_connection_list(void);
|
||||
|
||||
/* ------[ Control Channel Interfaces ]------------------------------------*/
|
||||
|
||||
typedef struct {
|
||||
int connected;
|
||||
int ref_count;
|
||||
int type;
|
||||
u32 remote_dom;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
control_if_t *interface;
|
||||
ctrl_back_ring_t tx_ring;
|
||||
ctrl_front_ring_t rx_ring;
|
||||
int virq;
|
||||
} control_channel_t;
|
||||
|
||||
/* cc types that we care about */
|
||||
#define CC_TYPE_INTERDOMAIN 0
|
||||
#define CC_TYPE_VIRQ 1
|
||||
|
||||
control_channel_t
|
||||
*ctrl_chan_new(u32 dom, int local_port, int remote_port);
|
||||
void ctrl_chan_free(control_channel_t *cc);
|
||||
int ctrl_chan_init(void);
|
||||
int ctrl_chan_notify(control_channel_t *cc);
|
||||
int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *);
|
||||
int ctrl_chan_write_request(control_channel_t *cc,
|
||||
xcs_control_msg_t *smsg);
|
||||
int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *);
|
||||
int ctrl_chan_write_response(control_channel_t *cc,
|
||||
xcs_control_msg_t *smsg);
|
||||
int ctrl_chan_request_to_read(control_channel_t *cc);
|
||||
int ctrl_chan_space_to_write_request(control_channel_t *cc);
|
||||
int ctrl_chan_response_to_read(control_channel_t *cc);
|
||||
int ctrl_chan_space_to_write_response(control_channel_t *cc);
|
||||
int ctrl_chan_connect(control_channel_t *cc);
|
||||
void ctrl_chan_disconnect(control_channel_t *cc);
|
||||
int ctrl_chan_bind_virq(int virq, int *port);
|
||||
|
||||
/* ------[ Event notification interfaces ]---------------------------------*/
|
||||
|
||||
|
||||
int evtchn_open(void);
|
||||
void evtchn_close();
|
||||
int evtchn_bind(int idx);
|
||||
int evtchn_unbind(int idx);
|
||||
void evtchn_unmask(u16 idx);
|
||||
int evtchn_read();
|
||||
|
||||
#endif /* __XCS_H__ */
|
||||
@@ -1,101 +0,0 @@
|
||||
/* xcs_proto.h
|
||||
*
|
||||
* protocol interfaces for the control interface switch (xcs).
|
||||
*
|
||||
* (c) 2004, Andrew Warfield
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XCS_PROTO_H__
|
||||
#define __XCS_PROTO_H__
|
||||
|
||||
#define XCS_SUN_PATH "/var/lib/xen/xcs_socket"
|
||||
|
||||
/* xcs message types: */
|
||||
#define XCS_CONNECT_CTRL 0 /* This is a control connection. */
|
||||
#define XCS_CONNECT_DATA 1 /* This is a data connection. */
|
||||
#define XCS_CONNECT_BYE 2 /* Terminate a session. */
|
||||
#define XCS_MSG_BIND 3 /* Register for a message type. */
|
||||
#define XCS_MSG_UNBIND 4 /* Unregister for a message type. */
|
||||
#define XCS_VIRQ_BIND 5 /* Register for a virq. */
|
||||
#define XCS_MSG_WRITELOCK 6 /* Writelock a (dom,type) pair. */
|
||||
#define XCS_CIF_NEW_CC 7 /* Create a new control channel. */
|
||||
#define XCS_CIF_FREE_CC 8 /* Create a new control channel. */
|
||||
#define XCS_REQUEST 9 /* This is a request message. */
|
||||
#define XCS_RESPONSE 10 /* this is a response Message. */
|
||||
#define XCS_VIRQ 11 /* this is a virq notification. */
|
||||
|
||||
/* xcs result values: */
|
||||
#define XCS_RSLT_OK 0
|
||||
#define XCS_RSLT_FAILED 1 /* something bad happened. */
|
||||
#define XCS_RSLT_ARECONNECTED 2 /* attempt to over connect. */
|
||||
#define XCS_RSLT_BADSESSION 3 /* request for unknown session id. */
|
||||
#define XCS_RSLT_NOSESSION 4 /* tried to do something before NEW. */
|
||||
#define XCS_RSLT_CONINUSE 5 /* Requested connection is taken. */
|
||||
#define XCS_RSLT_BADREQUEST 6 /* Request message didn't validate. */
|
||||
|
||||
/* Binding wildcards */
|
||||
#define PORT_WILDCARD 0xefffffff
|
||||
#define TYPE_WILDCARD 0xffff
|
||||
#define TYPE_VIRQ 0xfffe
|
||||
|
||||
typedef struct {
|
||||
unsigned long session_id;
|
||||
} xcs_connect_msg_t;
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
u16 type;
|
||||
} xcs_bind_msg_t;
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
u16 virq;
|
||||
} xcs_virq_msg_t;
|
||||
|
||||
typedef struct {
|
||||
u32 dom;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
} xcs_interface_msg_t;
|
||||
|
||||
typedef struct {
|
||||
u32 remote_dom;
|
||||
int local_port;
|
||||
control_msg_t msg;
|
||||
} xcs_control_msg_t;
|
||||
|
||||
typedef struct {
|
||||
u32 type;
|
||||
u32 result;
|
||||
union {
|
||||
xcs_connect_msg_t connect; /* These are xcs ctrl message types */
|
||||
xcs_bind_msg_t bind;
|
||||
xcs_virq_msg_t virq;
|
||||
xcs_interface_msg_t interface;
|
||||
|
||||
xcs_control_msg_t control; /* These are xcs data message types */
|
||||
} u;
|
||||
} xcs_msg_t;
|
||||
|
||||
/* message validation macros. */
|
||||
#define PORT_VALID(_p) \
|
||||
( (((_p) >= 0) && ((_p) < NR_EVENT_CHANNELS)) \
|
||||
|| ((_p) == PORT_WILDCARD) )
|
||||
|
||||
#define TYPE_VALID(_t) \
|
||||
( ((_t) < 256) \
|
||||
|| ((_t) == TYPE_VIRQ) \
|
||||
|| ((_t) == TYPE_WILDCARD) )
|
||||
|
||||
#define BIND_MSG_VALID(_b) \
|
||||
( PORT_VALID((_b)->port) && TYPE_VALID((_b)->type) )
|
||||
|
||||
/* Port is overwritten, and we don't currently validate the requested virq. */
|
||||
#define VIRQ_MSG_VALID(_v) ( 1 )
|
||||
|
||||
/* Interfaces may return with ports of -1, but may not be requested as such */
|
||||
#define INTERFACE_MSG_VALID(_i) \
|
||||
( PORT_VALID((_i)->local_port) && PORT_VALID((_i)->remote_port) )
|
||||
|
||||
#endif /* __XCS_PROTO_H__ */
|
||||
@@ -1,206 +0,0 @@
|
||||
/* xcsdump.c
|
||||
*
|
||||
* little tool to sniff control messages.
|
||||
*
|
||||
* Copyright (c) 2004, Andrew Warfield
|
||||
*
|
||||
* Modifications by Anthony Liguori <aliguori@us.ibm.com> are:
|
||||
* Copyright (C) 2005, International Business Machines, Corp.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <ctype.h>
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/io/domain_controller.h>
|
||||
#include <getopt.h>
|
||||
#include "xcs_proto.h"
|
||||
#include "xcs.h"
|
||||
|
||||
#include "dump.h"
|
||||
|
||||
static int xcs_ctrl_fd = -1; /* connection to the xcs server. */
|
||||
static int xcs_data_fd = -1; /* connection to the xcs server. */
|
||||
|
||||
int sock_connect(char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int ret, len, fd;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("error creating xcs socket!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, path);
|
||||
len = sizeof(addr.sun_family) + strlen(addr.sun_path) + 1;
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&addr, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("error connecting to xcs!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void sock_disconnect(int *fd)
|
||||
{
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
}
|
||||
|
||||
void xcs_read(int fd, xcs_msg_t *msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = read(fd, msg, sizeof(xcs_msg_t));
|
||||
if (ret != sizeof(xcs_msg_t)) {
|
||||
printf("read error\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void xcs_send(int fd, xcs_msg_t *msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = send(fd, msg, sizeof(xcs_msg_t), 0);
|
||||
if (ret != sizeof(xcs_msg_t) )
|
||||
{
|
||||
printf("send error\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int ret;
|
||||
xcs_msg_t msg;
|
||||
control_msg_t *cmsg;
|
||||
int verbose = 0;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hv:")) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'v':
|
||||
verbose = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
printf("Usage: %s [-v FLAGS]\n"
|
||||
"Displays XCS control message traffic.\n"
|
||||
"\n"
|
||||
"FLAGS is a bitmask where each bit (numbering starts from LSB) represents\n"
|
||||
"whether to display a particular message type.\n"
|
||||
"\n"
|
||||
"For example, -v 1022 will display all messages except for console messages.\n"
|
||||
, argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = sock_connect(XCS_SUN_PATH);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("connect failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
xcs_ctrl_fd = ret;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = XCS_CONNECT_CTRL;
|
||||
xcs_send(xcs_ctrl_fd, &msg);
|
||||
xcs_read(xcs_ctrl_fd, &msg);
|
||||
if (msg.result != XCS_RSLT_OK)
|
||||
{
|
||||
printf("Error connecting control channel\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ret = sock_connect(XCS_SUN_PATH);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("connect failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
xcs_data_fd = ret;
|
||||
|
||||
msg.type = XCS_CONNECT_DATA;
|
||||
/* session id is set from before... */
|
||||
xcs_send(xcs_data_fd, &msg);
|
||||
xcs_read(xcs_data_fd, &msg);
|
||||
if (msg.result != XCS_RSLT_OK)
|
||||
{
|
||||
printf("Error connecting data channel\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
msg.type = XCS_MSG_BIND;
|
||||
msg.u.bind.port = PORT_WILDCARD;
|
||||
msg.u.bind.type = TYPE_WILDCARD;
|
||||
xcs_send(xcs_ctrl_fd, &msg);
|
||||
xcs_read(xcs_ctrl_fd, &msg);
|
||||
if (msg.result != XCS_RSLT_OK)
|
||||
{
|
||||
printf("Error binding.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
xcs_read(xcs_data_fd, &msg);
|
||||
cmsg = &msg.u.control.msg;
|
||||
|
||||
switch (msg.type)
|
||||
{
|
||||
case XCS_REQUEST:
|
||||
if (!verbose || verbose & (1 << msg.u.control.msg.type))
|
||||
{
|
||||
printf("[REQUEST ] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
|
||||
msg.u.control.remote_dom,
|
||||
msg.u.control.local_port,
|
||||
msg.u.control.msg.type,
|
||||
msg.u.control.msg.subtype,
|
||||
msg.u.control.msg.length);
|
||||
|
||||
dump_msg(cmsg, verbose);
|
||||
}
|
||||
break;
|
||||
case XCS_RESPONSE:
|
||||
if (!verbose || verbose & (1 << msg.u.control.msg.type))
|
||||
{
|
||||
printf("[RESPONSE] : (dom:%u port:%d) (type:(%d,%d) len %d)\n",
|
||||
msg.u.control.remote_dom,
|
||||
msg.u.control.local_port,
|
||||
msg.u.control.msg.type,
|
||||
msg.u.control.msg.subtype,
|
||||
msg.u.control.msg.length);
|
||||
|
||||
dump_msg(cmsg, verbose);
|
||||
}
|
||||
break;
|
||||
case XCS_VIRQ:
|
||||
printf("[VIRQ ] : %d\n", msg.u.control.local_port);
|
||||
break;
|
||||
default:
|
||||
printf("[UNKNOWN ] : %d\n", msg.type);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -15,7 +15,6 @@ PROG_DEP = .*.d
|
||||
BASECFLAGS+= -O3 $(PROFILE)
|
||||
#BASECFLAGS+= -I$(XEN_ROOT)/tools
|
||||
BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
|
||||
BASECFLAGS+= -I$(XEN_ROOT)/tools/xcs
|
||||
BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public
|
||||
BASECFLAGS+= -I.
|
||||
BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public
|
||||
|
||||