ia64/xen-unstable

changeset 3366:a9ac02b7727d

bitkeeper revision 1.1159.1.525 (41d58ba8VgPwkfEiKrUXF8b7LLwQ5Q)

Andy's control-interface message switch -- first cut.
author kaf24@scramble.cl.cam.ac.uk
date Fri Dec 31 17:26:00 2004 +0000 (2004-12-31)
parents 9cee424e24de
children aa7ce8a31f3d f913da82d617
files .rootkeys BitKeeper/etc/ignore linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c tools/Makefile tools/libxc/xc_domain.c tools/misc/xend tools/python/setup.py tools/python/xen/lowlevel/xu/xu.c tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/channel.py tools/xcs/Makefile tools/xcs/bindings.c tools/xcs/connection.c tools/xcs/ctrl_interface.c tools/xcs/evtchn.c tools/xcs/xcs.c tools/xcs/xcs.h tools/xcs/xcs_proto.h tools/xcs/xcsdump.c xen/include/public/io/domain_controller.h
line diff
     1.1 --- a/.rootkeys	Fri Dec 31 13:53:32 2004 +0000
     1.2 +++ b/.rootkeys	Fri Dec 31 17:26:00 2004 +0000
     1.3 @@ -622,6 +622,15 @@ 4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d
     1.4  4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c
     1.5  4194e861x2eqNCD61RYPCUEBVdMYuw tools/x2d2/minixend.h
     1.6  4194e861A4V9VbD_FYmgXpYEj5YwVg tools/x2d2/util.c
     1.7 +41d58ba63w1WfBmd6Cr_18nhLNv7PA tools/xcs/Makefile
     1.8 +41d58ba6NxgkfzD_rmsGjgd_zJ3H_w tools/xcs/bindings.c
     1.9 +41d58ba6I2umi60mShq4Pl0RDg7lzQ tools/xcs/connection.c
    1.10 +41d58ba6YyYu53bFuoIAw9hNNmneEg tools/xcs/ctrl_interface.c
    1.11 +41d58ba6Ru9ZbhTjgYX_oiszSIwCww tools/xcs/evtchn.c
    1.12 +41d58ba6x9KO1CQBT7kKOKq_pJYC3g tools/xcs/xcs.c
    1.13 +41d58ba6R6foSMtSFEcu-yxWFrT8VQ tools/xcs/xcs.h
    1.14 +41d58ba6qyr2BkTcH2WlNBYLRyl2Yw tools/xcs/xcs_proto.h
    1.15 +41d58ba6ijEF6fedqRO5vFu7uCirZg tools/xcs/xcsdump.c
    1.16  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.17  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
    1.18  4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
     2.1 --- a/BitKeeper/etc/ignore	Fri Dec 31 13:53:32 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Fri Dec 31 17:26:00 2004 +0000
     2.3 @@ -75,6 +75,8 @@ tools/vnetd/vnetd
     2.4  tools/web-shutdown.tap
     2.5  tools/x2d2/minixend
     2.6  tools/xentrace/xentrace
     2.7 +tools/xcs/xcs
     2.8 +tools/xcs/xcsdump
     2.9  tools/xfrd/xfrd
    2.10  xen/BLOG
    2.11  xen/arch/x86/asm-offsets.s
     3.1 --- a/linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c	Fri Dec 31 13:53:32 2004 +0000
     3.2 +++ b/linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c	Fri Dec 31 17:26:00 2004 +0000
     3.3 @@ -47,6 +47,19 @@
     3.4  #endif
     3.5  
     3.6  /*
     3.7 + * Extra ring macros to sync a consumer index up to the public producer index. 
     3.8 + * Generally UNSAFE, but we use it for recovery and shutdown in some cases.
     3.9 + */
    3.10 +#define RING_DROP_PENDING_REQUESTS(_p, _r)                              \
    3.11 +    do {                                                                \
    3.12 +        (_r)->req_cons = (_r)->sring->req_prod;                         \
    3.13 +    } while (0)
    3.14 +#define RING_DROP_PENDING_RESPONSES(_p, _r)                             \
    3.15 +    do {                                                                \
    3.16 +        (_r)->rsp_cons = (_r)->sring->rsp_prod;                         \
    3.17 +    } while (0)
    3.18 +
    3.19 +/*
    3.20   * Only used by initial domain which must create its own control-interface
    3.21   * event channel. This value is picked up by the user-space domain controller
    3.22   * via an ioctl.
    3.23 @@ -59,8 +72,8 @@ static spinlock_t ctrl_if_lock;
    3.24  
    3.25  static struct irqaction ctrl_if_irq_action;
    3.26  
    3.27 -static CONTROL_RING_IDX ctrl_if_tx_resp_cons;
    3.28 -static CONTROL_RING_IDX ctrl_if_rx_req_cons;
    3.29 +static ctrl_front_ring_t ctrl_if_tx_ring;
    3.30 +static ctrl_back_ring_t  ctrl_if_rx_ring;
    3.31  
    3.32  /* Incoming message requests. */
    3.33      /* Primary message type -> message handler. */
    3.34 @@ -97,8 +110,6 @@ static void __ctrl_if_rx_tasklet(unsigne
    3.35  static DECLARE_TASKLET(ctrl_if_rx_tasklet, __ctrl_if_rx_tasklet, 0);
    3.36  
    3.37  #define get_ctrl_if() ((control_if_t *)((char *)HYPERVISOR_shared_info + 2048))
    3.38 -#define TX_FULL(_c)   \
    3.39 -    (((_c)->tx_req_prod - ctrl_if_tx_resp_cons) == CONTROL_RING_SIZE)
    3.40  
    3.41  static void ctrl_if_notify_controller(void)
    3.42  {
    3.43 @@ -113,21 +124,20 @@ static void ctrl_if_rxmsg_default_handle
    3.44  
    3.45  static void __ctrl_if_tx_tasklet(unsigned long data)
    3.46  {
    3.47 -    control_if_t *ctrl_if = get_ctrl_if();
    3.48 -    ctrl_msg_t   *msg;
    3.49 -    int           was_full = TX_FULL(ctrl_if);
    3.50 -    CONTROL_RING_IDX rp;
    3.51 +    ctrl_msg_t *msg;
    3.52 +    int         was_full = RING_FULL(CTRL_RING, &ctrl_if_tx_ring);
    3.53 +    RING_IDX    i, rp;
    3.54  
    3.55 -    rp = ctrl_if->tx_resp_prod;
    3.56 +    i  = ctrl_if_tx_ring.rsp_cons;
    3.57 +    rp = ctrl_if_tx_ring.sring->rsp_prod;
    3.58      rmb(); /* Ensure we see all requests up to 'rp'. */
    3.59  
    3.60 -    while ( ctrl_if_tx_resp_cons != rp )
    3.61 +    for ( ; i != rp; i++ )
    3.62      {
    3.63 -        msg = &ctrl_if->tx_ring[MASK_CONTROL_IDX(ctrl_if_tx_resp_cons)];
    3.64 -
    3.65 -        DPRINTK("Rx-Rsp %u/%u :: %d/%d\n", 
    3.66 -                ctrl_if_tx_resp_cons,
    3.67 -                ctrl_if->tx_resp_prod,
    3.68 +        msg = RING_GET_RESPONSE(CTRL_RING, &ctrl_if_tx_ring, i);
    3.69 +        
    3.70 +        DPRINTK("Rx-Rsp %u/%u :: %d/%d\n", i-1,
    3.71 +                ctrl_if_tx_ring.sring->rsp_prod,
    3.72                  msg->type, msg->subtype);
    3.73  
    3.74          /* Execute the callback handler, if one was specified. */
    3.75 @@ -138,16 +148,16 @@ static void __ctrl_if_tx_tasklet(unsigne
    3.76              smp_mb(); /* Execute, /then/ free. */
    3.77              ctrl_if_txmsg_id_mapping[msg->id].fn = NULL;
    3.78          }
    3.79 -
    3.80 -        /*
    3.81 -         * Step over the message in the ring /after/ finishing reading it. As 
    3.82 -         * soon as the index is updated then the message may get blown away.
    3.83 -         */
    3.84 -        smp_mb();
    3.85 -        ctrl_if_tx_resp_cons++;
    3.86      }
    3.87  
    3.88 -    if ( was_full && !TX_FULL(ctrl_if) )
    3.89 +    /*
    3.90 +     * Step over messages in the ring /after/ finishing reading them. As soon 
    3.91 +     * as the index is updated then the message may get blown away.
    3.92 +     */
    3.93 +    smp_mb();
    3.94 +    ctrl_if_tx_ring.rsp_cons = i;
    3.95 +            
    3.96 +    if ( was_full && !RING_FULL(CTRL_RING, &ctrl_if_tx_ring) )
    3.97      {
    3.98          wake_up(&ctrl_if_tx_wait);
    3.99          run_task_queue(&ctrl_if_tx_tq);
   3.100 @@ -172,24 +182,27 @@ static void __ctrl_if_rxmsg_deferred(voi
   3.101  
   3.102  static void __ctrl_if_rx_tasklet(unsigned long data)
   3.103  {
   3.104 -    control_if_t *ctrl_if = get_ctrl_if();
   3.105      ctrl_msg_t    msg, *pmsg;
   3.106 -    CONTROL_RING_IDX rp, dp;
   3.107 +    CONTROL_RING_IDX dp;
   3.108 +    RING_IDX rp, i;
   3.109  
   3.110 +    i  = ctrl_if_rx_ring.req_cons;
   3.111 +    rp = ctrl_if_rx_ring.sring->req_prod;
   3.112      dp = ctrl_if_rxmsg_deferred_prod;
   3.113 -    rp = ctrl_if->rx_req_prod;
   3.114      rmb(); /* Ensure we see all requests up to 'rp'. */
   3.115 -
   3.116 -    while ( ctrl_if_rx_req_cons != rp )
   3.117 + 
   3.118 +    for ( ; i != rp; i++) 
   3.119      {
   3.120 -        pmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if_rx_req_cons++)];
   3.121 +        pmsg = RING_GET_REQUEST(CTRL_RING, &ctrl_if_rx_ring, i);
   3.122          memcpy(&msg, pmsg, offsetof(ctrl_msg_t, msg));
   3.123  
   3.124 -        DPRINTK("Rx-Req %u/%u :: %d/%d\n", 
   3.125 -                ctrl_if_rx_req_cons-1,
   3.126 -                ctrl_if->rx_req_prod,
   3.127 +        DPRINTK("Rx-Req %u/%u :: %d/%d\n", i-1,
   3.128 +                ctrl_if_rx_ring.sring->req_prod,
   3.129                  msg.type, msg.subtype);
   3.130  
   3.131 +        if ( msg.length > sizeof(msg.msg) )
   3.132 +            msg.length = sizeof(msg.msg);
   3.133 +        
   3.134          if ( msg.length != 0 )
   3.135              memcpy(msg.msg, pmsg->msg, msg.length);
   3.136  
   3.137 @@ -201,6 +214,8 @@ static void __ctrl_if_rx_tasklet(unsigne
   3.138              (*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
   3.139      }
   3.140  
   3.141 +    ctrl_if_rx_ring.req_cons = i;
   3.142 +
   3.143      if ( dp != ctrl_if_rxmsg_deferred_prod )
   3.144      {
   3.145          wmb();
   3.146 @@ -212,12 +227,10 @@ static void __ctrl_if_rx_tasklet(unsigne
   3.147  static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id,
   3.148                                       struct pt_regs *regs)
   3.149  {
   3.150 -    control_if_t *ctrl_if = get_ctrl_if();
   3.151 -
   3.152 -    if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
   3.153 +    if ( RING_HAS_UNCONSUMED_RESPONSES(CTRL_RING, &ctrl_if_tx_ring) )
   3.154          tasklet_schedule(&ctrl_if_tx_tasklet);
   3.155  
   3.156 -    if ( ctrl_if_rx_req_cons != ctrl_if->rx_req_prod )
   3.157 +    if ( RING_HAS_UNCONSUMED_REQUESTS(CTRL_RING, &ctrl_if_rx_ring) )
   3.158          tasklet_schedule(&ctrl_if_rx_tasklet);
   3.159  
   3.160      return IRQ_HANDLED;
   3.161 @@ -229,13 +242,13 @@ ctrl_if_send_message_noblock(
   3.162      ctrl_msg_handler_t hnd,
   3.163      unsigned long id)
   3.164  {
   3.165 -    control_if_t *ctrl_if = get_ctrl_if();
   3.166      unsigned long flags;
   3.167 +    ctrl_msg_t   *dmsg;
   3.168      int           i;
   3.169  
   3.170      spin_lock_irqsave(&ctrl_if_lock, flags);
   3.171  
   3.172 -    if ( TX_FULL(ctrl_if) )
   3.173 +    if ( RING_FULL(CTRL_RING, &ctrl_if_tx_ring) )
   3.174      {
   3.175          spin_unlock_irqrestore(&ctrl_if_lock, flags);
   3.176          return -EAGAIN;
   3.177 @@ -252,14 +265,15 @@ ctrl_if_send_message_noblock(
   3.178      }
   3.179  
   3.180      DPRINTK("Tx-Req %u/%u :: %d/%d\n", 
   3.181 -            ctrl_if->tx_req_prod, 
   3.182 -            ctrl_if_tx_resp_cons,
   3.183 +            ctrl_if_tx_ring.req_prod_pvt, 
   3.184 +            ctrl_if_tx_ring.rsp_cons,
   3.185              msg->type, msg->subtype);
   3.186  
   3.187 -    memcpy(&ctrl_if->tx_ring[MASK_CONTROL_IDX(ctrl_if->tx_req_prod)], 
   3.188 -           msg, sizeof(*msg));
   3.189 -    wmb(); /* Write the message before letting the controller peek at it. */
   3.190 -    ctrl_if->tx_req_prod++;
   3.191 +    dmsg = RING_GET_REQUEST(CTRL_RING, &ctrl_if_tx_ring, 
   3.192 +            ctrl_if_tx_ring.req_prod_pvt);
   3.193 +    memcpy(dmsg, msg, sizeof(*msg));
   3.194 +    ctrl_if_tx_ring.req_prod_pvt++;
   3.195 +    RING_PUSH_REQUESTS(CTRL_RING, &ctrl_if_tx_ring);
   3.196  
   3.197      spin_unlock_irqrestore(&ctrl_if_lock, flags);
   3.198  
   3.199 @@ -358,10 +372,8 @@ int
   3.200  ctrl_if_enqueue_space_callback(
   3.201      struct tq_struct *task)
   3.202  {
   3.203 -    control_if_t *ctrl_if = get_ctrl_if();
   3.204 -
   3.205      /* Fast path. */
   3.206 -    if ( !TX_FULL(ctrl_if) )
   3.207 +    if ( !RING_FULL(CTRL_RING, &ctrl_if_tx_ring) )
   3.208          return 0;
   3.209  
   3.210      (void)queue_task(task, &ctrl_if_tx_tq);
   3.211 @@ -372,14 +384,13 @@ ctrl_if_enqueue_space_callback(
   3.212       * certainly return 'not full'.
   3.213       */
   3.214      smp_mb();
   3.215 -    return TX_FULL(ctrl_if);
   3.216 +    return RING_FULL(CTRL_RING, &ctrl_if_tx_ring);
   3.217  }
   3.218  
   3.219  void
   3.220  ctrl_if_send_response(
   3.221      ctrl_msg_t *msg)
   3.222  {
   3.223 -    control_if_t *ctrl_if = get_ctrl_if();
   3.224      unsigned long flags;
   3.225      ctrl_msg_t   *dmsg;
   3.226  
   3.227 @@ -390,15 +401,16 @@ ctrl_if_send_response(
   3.228      spin_lock_irqsave(&ctrl_if_lock, flags);
   3.229  
   3.230      DPRINTK("Tx-Rsp %u :: %d/%d\n", 
   3.231 -            ctrl_if->rx_resp_prod, 
   3.232 +            ctrl_if_rx_ring.rsp_prod_pvt, 
   3.233              msg->type, msg->subtype);
   3.234  
   3.235 -    dmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if->rx_resp_prod)];
   3.236 +    dmsg = RING_GET_RESPONSE(CTRL_RING, &ctrl_if_rx_ring, 
   3.237 +            ctrl_if_rx_ring.rsp_prod_pvt);
   3.238      if ( dmsg != msg )
   3.239          memcpy(dmsg, msg, sizeof(*msg));
   3.240  
   3.241 -    wmb(); /* Write the message before letting the controller peek at it. */
   3.242 -    ctrl_if->rx_resp_prod++;
   3.243 +    ctrl_if_rx_ring.rsp_prod_pvt++;
   3.244 +    RING_PUSH_RESPONSES(CTRL_RING, &ctrl_if_rx_ring);
   3.245  
   3.246      spin_unlock_irqrestore(&ctrl_if_lock, flags);
   3.247  
   3.248 @@ -469,8 +481,6 @@ void ctrl_if_suspend(void)
   3.249  
   3.250  void ctrl_if_resume(void)
   3.251  {
   3.252 -    control_if_t *ctrl_if = get_ctrl_if();
   3.253 -
   3.254      if ( xen_start_info.flags & SIF_INITDOMAIN )
   3.255      {
   3.256          /*
   3.257 @@ -491,8 +501,8 @@ void ctrl_if_resume(void)
   3.258      }
   3.259  
   3.260      /* Sync up with shared indexes. */
   3.261 -    ctrl_if_tx_resp_cons = ctrl_if->tx_resp_prod;
   3.262 -    ctrl_if_rx_req_cons  = ctrl_if->rx_resp_prod;
   3.263 +    RING_DROP_PENDING_RESPONSES(CTRL_RING, &ctrl_if_tx_ring);
   3.264 +    RING_DROP_PENDING_REQUESTS(CTRL_RING, &ctrl_if_rx_ring);
   3.265  
   3.266      ctrl_if_evtchn = xen_start_info.domain_controller_evtchn;
   3.267      ctrl_if_irq    = bind_evtchn_to_irq(ctrl_if_evtchn);
   3.268 @@ -505,11 +515,15 @@ void ctrl_if_resume(void)
   3.269  
   3.270  void __init ctrl_if_init(void)
   3.271  {
   3.272 -        int i;
   3.273 +    control_if_t *ctrl_if = get_ctrl_if();
   3.274 +    int i;
   3.275  
   3.276      for ( i = 0; i < 256; i++ )
   3.277          ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
   3.278  
   3.279 +    FRONT_RING_ATTACH(CTRL_RING, &ctrl_if_tx_ring, &ctrl_if->tx_ring);
   3.280 +    BACK_RING_ATTACH(CTRL_RING, &ctrl_if_rx_ring, &ctrl_if->rx_ring);
   3.281 +    
   3.282      spin_lock_init(&ctrl_if_lock);
   3.283  
   3.284      ctrl_if_resume();
   3.285 @@ -532,12 +546,13 @@ static int __init ctrl_if_late_setup(voi
   3.286  
   3.287  int ctrl_if_transmitter_empty(void)
   3.288  {
   3.289 -    return (get_ctrl_if()->tx_req_prod == ctrl_if_tx_resp_cons);
   3.290 +    return (ctrl_if_tx_ring.sring->req_prod == ctrl_if_tx_ring.rsp_cons);
   3.291 +    
   3.292  }
   3.293  
   3.294  void ctrl_if_discard_responses(void)
   3.295  {
   3.296 -    ctrl_if_tx_resp_cons = get_ctrl_if()->tx_resp_prod;
   3.297 +    RING_DROP_PENDING_RESPONSES(CTRL_RING, &ctrl_if_tx_ring);
   3.298  }
   3.299  
   3.300  EXPORT_SYMBOL(ctrl_if_send_message_noblock);
     4.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c	Fri Dec 31 13:53:32 2004 +0000
     4.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c	Fri Dec 31 17:26:00 2004 +0000
     4.3 @@ -61,8 +61,8 @@ static devfs_handle_t xen_dev_dir;
     4.4  
     4.5  struct per_user_data {
     4.6      /* Notification ring, accessed via /dev/xen/evtchn. */
     4.7 -#   define RING_SIZE     2048  /* 2048 16-bit entries */
     4.8 -#   define RING_MASK(_i) ((_i)&(RING_SIZE-1))
     4.9 +#   define EVTCHN_RING_SIZE     2048  /* 2048 16-bit entries */
    4.10 +#   define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
    4.11      u16 *ring;
    4.12      unsigned int ring_cons, ring_prod, ring_overflow;
    4.13  
    4.14 @@ -86,9 +86,9 @@ void evtchn_device_upcall(int port)
    4.15  
    4.16      if ( (u = port_user[port]) != NULL )
    4.17      {
    4.18 -        if ( (u->ring_prod - u->ring_cons) < RING_SIZE )
    4.19 +        if ( (u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE )
    4.20          {
    4.21 -            u->ring[RING_MASK(u->ring_prod)] = (u16)port;
    4.22 +            u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
    4.23              if ( u->ring_cons == u->ring_prod++ )
    4.24              {
    4.25                  wake_up_interruptible(&u->evtchn_wait);
    4.26 @@ -154,10 +154,10 @@ static ssize_t evtchn_read(struct file *
    4.27      }
    4.28  
    4.29      /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
    4.30 -    if ( ((c ^ p) & RING_SIZE) != 0 )
    4.31 +    if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 )
    4.32      {
    4.33 -        bytes1 = (RING_SIZE - RING_MASK(c)) * sizeof(u16);
    4.34 -        bytes2 = RING_MASK(p) * sizeof(u16);
    4.35 +        bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(u16);
    4.36 +        bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
    4.37      }
    4.38      else
    4.39      {
    4.40 @@ -176,7 +176,7 @@ static ssize_t evtchn_read(struct file *
    4.41          bytes2 = count - bytes1;
    4.42      }
    4.43  
    4.44 -    if ( copy_to_user(buf, &u->ring[RING_MASK(c)], bytes1) ||
    4.45 +    if ( copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
    4.46           ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) )
    4.47      {
    4.48          rc = -EFAULT;
     5.1 --- a/tools/Makefile	Fri Dec 31 13:53:32 2004 +0000
     5.2 +++ b/tools/Makefile	Fri Dec 31 17:26:00 2004 +0000
     5.3 @@ -8,6 +8,7 @@ all:
     5.4  	$(MAKE) -C xentrace
     5.5  	$(MAKE) -C python
     5.6  	$(MAKE) -C xfrd
     5.7 +	$(MAKE) -C xcs
     5.8  
     5.9  install: 
    5.10  ifneq ($(dist),yes)
    5.11 @@ -21,6 +22,7 @@ endif
    5.12  	$(MAKE) -C python install
    5.13  	$(MAKE) -C xfrd install
    5.14  	$(MAKE) -C sv install
    5.15 +	$(MAKE) -C xcs install
    5.16  
    5.17  dist: $(TARGET)
    5.18  	$(MAKE) prefix=`pwd`/../../install dist=yes install
    5.19 @@ -34,4 +36,5 @@ clean:
    5.20  	$(MAKE) -C xentrace clean
    5.21  	$(MAKE) -C python clean
    5.22  	$(MAKE) -C xfrd clean
    5.23 +	$(MAKE) -C xcs clean
    5.24  
     6.1 --- a/tools/libxc/xc_domain.c	Fri Dec 31 13:53:32 2004 +0000
     6.2 +++ b/tools/libxc/xc_domain.c	Fri Dec 31 17:26:00 2004 +0000
     6.3 @@ -69,7 +69,7 @@ int xc_domain_pincpu(int xc_handle,
     6.4      dom0_op_t op;
     6.5      op.cmd = DOM0_PINCPUDOMAIN;
     6.6      op.u.pincpudomain.domain = (domid_t)domid;
     6.7 -    op.u.pincpudomain.exec_domain = 0; 
     6.8 +    op.u.pincpudomain.exec_domain = 0;
     6.9      op.u.pincpudomain.cpu  = cpu;
    6.10      return do_dom0_op(xc_handle, &op);
    6.11  }
     7.1 --- a/tools/misc/xend	Fri Dec 31 13:53:32 2004 +0000
     7.2 +++ b/tools/misc/xend	Fri Dec 31 17:26:00 2004 +0000
     7.3 @@ -21,6 +21,12 @@
     7.4  """
     7.5  import os
     7.6  import sys
     7.7 +import socket
     7.8 +import time
     7.9 +
    7.10 +XCS_PORT = 1633
    7.11 +XCS_EXEC = "/usr/sbin/xcs"
    7.12 +XCS_LOGFILE = "/var/log/xcs.log"
    7.13  
    7.14  # Default install path for Xen binary packages.
    7.15  sys.path.append('/lib/python')
    7.16 @@ -89,6 +95,18 @@ def check_user():
    7.17          msg("Xend must be run as root.")
    7.18          hline()
    7.19          raise CheckError("invalid user")
    7.20 +
    7.21 +def xcs_running():
    7.22 +    """ See if the control switch is running.
    7.23 +    """
    7.24 +    ret = 1
    7.25 +    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    7.26 +    try:
    7.27 +        s.connect( ("127.0.0.1", XCS_PORT) )
    7.28 +    except:
    7.29 +        ret = 0
    7.30 +    s.close()
    7.31 +    return (ret)
    7.32      
    7.33  def main():
    7.34      try:
    7.35 @@ -97,6 +115,31 @@ def main():
    7.36          check_user()
    7.37      except CheckError:
    7.38          sys.exit(1)
    7.39 +    
    7.40 +    if (not xcs_running()):
    7.41 +        if os.fork():
    7.42 +            time.sleep(1) # let xcs start
    7.43 +        else:
    7.44 +            try:
    7.45 +                logfile = os.open(XCS_LOGFILE, 
    7.46 +                                  os.O_WRONLY|os.O_APPEND|os.O_CREAT)
    7.47 +                os.close(1)
    7.48 +                os.dup(logfile)
    7.49 +                os.close(2)
    7.50 +                os.dup(logfile)
    7.51 +                os.close(logfile)
    7.52 +                os.execlp(XCS_EXEC, XCS_EXEC)
    7.53 +            except:
    7.54 +                hline()
    7.55 +                msg("Tried to start xcs, but failed. Is it installed?")
    7.56 +                hline()
    7.57 +                raise CheckError("couldn't start xcs")
    7.58 +        if (not xcs_running()):
    7.59 +            hline()
    7.60 +            msg("Failed to start the control interface switch.")
    7.61 +            hline()
    7.62 +            raise CheckError("xcs not running")
    7.63 +        
    7.64      daemon = SrvDaemon.instance()
    7.65      if not sys.argv[1:]:
    7.66          print 'usage: %s {start|stop|restart}' % sys.argv[0]
     8.1 --- a/tools/python/setup.py	Fri Dec 31 13:53:32 2004 +0000
     8.2 +++ b/tools/python/setup.py	Fri Dec 31 17:26:00 2004 +0000
     8.3 @@ -10,6 +10,7 @@ extra_compile_args  = [ "-fno-strict-ali
     8.4  include_dirs = [ XEN_ROOT + "/tools/python/xen/lowlevel/xu",
     8.5                   XEN_ROOT + "/tools/libxc",
     8.6                   XEN_ROOT + "/tools/libxutil",
     8.7 +                 XEN_ROOT + "/tools/xcs",
     8.8                   ]
     8.9  
    8.10  library_dirs = [ XEN_ROOT + "/tools/libxc",
     9.1 --- a/tools/python/xen/lowlevel/xu/xu.c	Fri Dec 31 13:53:32 2004 +0000
     9.2 +++ b/tools/python/xen/lowlevel/xu/xu.c	Fri Dec 31 17:26:00 2004 +0000
     9.3 @@ -59,6 +59,7 @@
     9.4  
     9.5  /* Set the close-on-exec flag on a file descriptor.  Doesn't currently bother
     9.6   * to check for errors. */
     9.7 +/*
     9.8  static void set_cloexec(int fd)
     9.9  {
    9.10      int flags = fcntl(fd, F_GETFD, 0);
    9.11 @@ -69,7 +70,222 @@ static void set_cloexec(int fd)
    9.12      flags |= FD_CLOEXEC;
    9.13      fcntl(fd, F_SETFD, flags);
    9.14  }
    9.15 +*/
    9.16 +/*
    9.17 + * *********************** XCS INTERFACE ***********************
    9.18 + */
    9.19  
    9.20 +#include <arpa/inet.h>
    9.21 +#include <xcs_proto.h>
    9.22 +
    9.23 +static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
    9.24 +static int xcs_data_fd = -1; /*    data connection to the xcs server. */
    9.25 +static u32 xcs_session_id = 0;
    9.26 +
    9.27 +int xcs_ctrl_send(xcs_msg_t *msg);
    9.28 +int xcs_ctrl_read(xcs_msg_t *msg);
    9.29 +int xcs_data_send(xcs_msg_t *msg);
    9.30 +int xcs_data_read(xcs_msg_t *msg);
    9.31 +
    9.32 +int xcs_connect(char *ip, short port)
    9.33 +{
    9.34 +    struct sockaddr_in addr;
    9.35 +    int ret, flags;
    9.36 +    xcs_msg_t msg;
    9.37 +
    9.38 +    if (xcs_data_fd != -1) /* already connected */
    9.39 +        return 0;
    9.40 +    
    9.41 +    xcs_ctrl_fd = socket(AF_INET, SOCK_STREAM, 0);
    9.42 +    if (xcs_ctrl_fd < 0)
    9.43 +    {
    9.44 +        printf("error creating xcs socket!\n");
    9.45 +        goto fail;
    9.46 +    }
    9.47 +    
    9.48 +    addr.sin_family = AF_INET;
    9.49 +    addr.sin_port = htons(port);
    9.50 +    addr.sin_addr.s_addr = inet_addr(ip);
    9.51 +    memset(&(addr.sin_zero), '\0', 8);
    9.52 +
    9.53 +    ret = connect(xcs_ctrl_fd, (struct sockaddr *)&addr, 
    9.54 +            sizeof(struct sockaddr));
    9.55 +    if (ret < 0) 
    9.56 +    {
    9.57 +        printf("error connecting to xcs(ctrl)! (%d)\n", errno);
    9.58 +        goto ctrl_fd_fail;
    9.59 +    }
    9.60 +
    9.61 +    //set_cloexec(xcs_ctrl_fd);
    9.62 +            
    9.63 +    msg.type = XCS_CONNECT_CTRL;
    9.64 +    msg.u.connect.session_id = xcs_session_id;
    9.65 +    xcs_ctrl_send(&msg);
    9.66 +    xcs_ctrl_read(&msg); /* TODO: timeout + error! */
    9.67 +    
    9.68 +    if (msg.result != XCS_RSLT_OK)
    9.69 +    {
    9.70 +        printf("error connecting xcs control channel!\n");
    9.71 +        goto ctrl_fd_fail;
    9.72 +    }
    9.73 +    xcs_session_id = msg.u.connect.session_id;
    9.74 +    
    9.75 +    /* now the data connection. */
    9.76 +    xcs_data_fd = socket(AF_INET, SOCK_STREAM, 0);
    9.77 +    if (xcs_data_fd < 0)
    9.78 +    {
    9.79 +        printf("error creating xcs data socket!\n");
    9.80 +        goto ctrl_fd_fail;
    9.81 +    }
    9.82 +    
    9.83 +    addr.sin_family = AF_INET;
    9.84 +    addr.sin_port = htons(port);
    9.85 +    addr.sin_addr.s_addr = inet_addr(ip);
    9.86 +    memset(&(addr.sin_zero), '\0', 8);
    9.87 +    
    9.88 +    ret = connect(xcs_data_fd, (struct sockaddr *)&addr, 
    9.89 +            sizeof(struct sockaddr));
    9.90 +    if (ret < 0) 
    9.91 +    {
    9.92 +        printf("error connecting to xcs(data)! (%d)\n", errno);
    9.93 +        goto data_fd_fail;
    9.94 +    }
    9.95 +
    9.96 +    //set_cloexec(xcs_data_fd);
    9.97 +    msg.type = XCS_CONNECT_DATA;
    9.98 +    msg.u.connect.session_id = xcs_session_id;
    9.99 +    xcs_data_send(&msg);
   9.100 +    xcs_data_read(&msg); /* TODO: timeout + error! */
   9.101 +    
   9.102 +    if (msg.result != XCS_RSLT_OK)
   9.103 +    {
   9.104 +        printf("error connecting xcs control channel!\n");
   9.105 +        goto ctrl_fd_fail;
   9.106 +    }
   9.107 +    
   9.108 +    if ( ((flags = fcntl(xcs_data_fd, F_GETFL, 0)) < 0) ||
   9.109 +        (fcntl(xcs_data_fd, F_SETFL, flags | O_NONBLOCK) < 0) )
   9.110 +    {
   9.111 +        printf("Unable to set non-blocking status on data socket.");
   9.112 +        goto data_fd_fail;
   9.113 +    }
   9.114 +    
   9.115 +    /* Haven't put type binding hooks into Xend yet. */
   9.116 +    /* for now, register for everything:             */
   9.117 +    /*
   9.118 +    msg.type = XCS_MSG_BIND;
   9.119 +    msg.u.bind.port = PORT_WILDCARD;
   9.120 +    msg.u.bind.type = TYPE_WILDCARD;
   9.121 +    xcs_ctrl_send(&msg);
   9.122 +    xcs_ctrl_read(&msg);
   9.123 +    
   9.124 +    if (msg.result != XCS_RSLT_OK)
   9.125 +    {
   9.126 +        printf("error binding!\n");
   9.127 +        goto data_fd_fail;
   9.128 +    }
   9.129 +    printf("successfully connected to xcs.\n");
   9.130 +    */
   9.131 +    return 0;
   9.132 +
   9.133 +data_fd_fail: 
   9.134 +    close(xcs_data_fd);  
   9.135 +    xcs_data_fd = -1;  
   9.136 +    
   9.137 +ctrl_fd_fail:
   9.138 +    close(xcs_ctrl_fd);
   9.139 +    xcs_ctrl_fd = -1; 
   9.140 +     
   9.141 +fail:
   9.142 +    return -1;
   9.143 +    
   9.144 +}
   9.145 +
   9.146 +void xcs_disconnect(void)
   9.147 +{
   9.148 +    printf("xcs_disconnect called!\n");
   9.149 +    close(xcs_data_fd);
   9.150 +    xcs_data_fd = -1;
   9.151 +    close(xcs_ctrl_fd);
   9.152 +    xcs_ctrl_fd = -1;
   9.153 +}
   9.154 +
   9.155 +int xcs_ctrl_read(xcs_msg_t *msg)
   9.156 +{
   9.157 +    int ret;
   9.158 +    
   9.159 +    ret = read(xcs_ctrl_fd, msg, sizeof(xcs_msg_t));
   9.160 +    if (ret != sizeof(xcs_msg_t)) {
   9.161 +        printf("xu-xcs: ctrl read error (%d)\n", errno);
   9.162 +        /* TODO: set xcs_fd to -1 if the connection has been dropped. */
   9.163 +    } else {
   9.164 +        printf("xu-xcs: read! fd: %d, type: %u\n", xcs_ctrl_fd, msg->type);
   9.165 +    }
   9.166 +    return ret;
   9.167 +}
   9.168 +
   9.169 +int xcs_ctrl_send(xcs_msg_t *msg)
   9.170 +{
   9.171 +    int ret;
   9.172 +    
   9.173 +    ret = send(xcs_ctrl_fd, msg, sizeof(xcs_msg_t), 0);
   9.174 +    if (ret != sizeof(xcs_msg_t) )
   9.175 +    {
   9.176 +        printf("xu-xcs: ctrl send error(%d)\n", errno);
   9.177 +        /* TODO: set xcs_fd to -1 if the connection has been dropped. */
   9.178 +    } else {
   9.179 +        printf("xu-xcs: sent! fd: %d, type: %u\n", xcs_ctrl_fd, msg->type);
   9.180 +    }
   9.181 +    return ret;
   9.182 +}
   9.183 +
   9.184 +int xcs_data_read(xcs_msg_t *msg)
   9.185 +{
   9.186 +    int ret;
   9.187 +    
   9.188 +    ret = read(xcs_data_fd, msg, sizeof(xcs_msg_t));
   9.189 +    if (ret != sizeof(xcs_msg_t)) {
   9.190 +        printf("xu-xcs: ctrl read error (%d)\n", errno);
   9.191 +        /* TODO: set xcs_fd to -1 if the connection has been dropped. */
   9.192 +    }
   9.193 +    return ret;
   9.194 +}
   9.195 +
   9.196 +int xcs_data_send(xcs_msg_t *msg)
   9.197 +{
   9.198 +    int ret;
   9.199 +    
   9.200 +    ret = send(xcs_data_fd, msg, sizeof(xcs_msg_t), 0);
   9.201 +    if (ret != sizeof(xcs_msg_t) )
   9.202 +    {
   9.203 +        printf("xu-xcs: ctrl send error(%d)\n", errno);
   9.204 +        /* TODO: set xcs_fd to -1 if the connection has been dropped. */
   9.205 +    }
   9.206 +    return ret;
   9.207 +}
   9.208 +
   9.209 +
   9.210 +typedef struct kme_st {
   9.211 +    xcs_msg_t         msg;
   9.212 +    struct kme_st    *next;
   9.213 +} xcs_msg_ent_t;
   9.214 +    
   9.215 +
   9.216 +#define XCS_RING_SIZE 64
   9.217 +static xcs_msg_ent_t *req_ring[64];
   9.218 +static unsigned req_prod = 0;
   9.219 +static unsigned req_cons = 0;
   9.220 +
   9.221 +static xcs_msg_ent_t *rsp_ring[64];
   9.222 +static unsigned rsp_prod = 0;
   9.223 +static unsigned rsp_cons = 0;
   9.224 +
   9.225 +#define REQ_RING_ENT(_idx) (req_ring[(_idx) % XCS_RING_SIZE])
   9.226 +#define RSP_RING_ENT(_idx) (rsp_ring[(_idx) % XCS_RING_SIZE]) 
   9.227 +#define REQ_RING_FULL ( req_prod - req_cons == XCS_RING_SIZE )
   9.228 +#define RSP_RING_FULL ( rsp_prod - rsp_cons == XCS_RING_SIZE )
   9.229 +#define REQ_RING_EMPTY ( req_prod == req_cons )
   9.230 +#define RSP_RING_EMPTY ( rsp_prod == rsp_cons )
   9.231  /*
   9.232   * *********************** NOTIFIER ***********************
   9.233   */
   9.234 @@ -81,81 +297,142 @@ typedef struct {
   9.235  
   9.236  static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
   9.237  {
   9.238 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.239 -    u16 v;
   9.240 -    int bytes;
   9.241 +    xcs_msg_ent_t *ent;
   9.242 +    int ret;
   9.243  
   9.244      if ( !PyArg_ParseTuple(args, "") )
   9.245          return NULL;
   9.246 -    
   9.247 -    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
   9.248 +    printf("xu_notifier_read()\n");
   9.249 +         
   9.250 +    while ((!REQ_RING_FULL) && (!RSP_RING_FULL))
   9.251      {
   9.252 -        if ( errno == EINTR )
   9.253 +        ent = (xcs_msg_ent_t *)malloc(sizeof(xcs_msg_ent_t));
   9.254 +        ret = xcs_data_read(&ent->msg);
   9.255 +
   9.256 +        if (ret == -1)
   9.257 +        {
   9.258 +            free(ent);
   9.259 +            if ( errno == EINTR )
   9.260 +                continue;
   9.261 +            if ( errno == EAGAIN )
   9.262 +                break;
   9.263 +            return PyErr_SetFromErrno(PyExc_IOError);
   9.264 +        }
   9.265 +        printf("notifier got msg type %u\n", ent->msg.type);
   9.266 +        switch (ent->msg.type)
   9.267 +        {
   9.268 +        case XCS_REQUEST:
   9.269 +            REQ_RING_ENT(req_prod) = ent;
   9.270 +            req_prod++;
   9.271              continue;
   9.272 -        if ( errno == EAGAIN )
   9.273 -            goto none;
   9.274 -        return PyErr_SetFromErrno(PyExc_IOError);
   9.275 +
   9.276 +        case XCS_RESPONSE:
   9.277 +            RSP_RING_ENT(rsp_prod) = ent;
   9.278 +            rsp_prod++;
   9.279 +            continue;
   9.280 +            
   9.281 +        case XCS_VIRQ:
   9.282 +            ret = ent->msg.u.control.local_port;
   9.283 +            free(ent);
   9.284 +            return PyInt_FromLong(ret);
   9.285 +
   9.286 +        default:
   9.287 +            printf("Throwing away xcs msg type: %u\n", ent->msg.type);
   9.288 +            free(ent);
   9.289 +        }
   9.290      }
   9.291      
   9.292 -    if ( bytes == sizeof(v) )
   9.293 -        return PyInt_FromLong(v);
   9.294 -
   9.295 - none:
   9.296 +    if (!REQ_RING_EMPTY) 
   9.297 +    {
   9.298 +        printf("nfy: req: %d\n", 
   9.299 +                REQ_RING_ENT(req_cons)->msg.u.control.local_port);
   9.300 +        return PyInt_FromLong(REQ_RING_ENT(req_cons)->msg.u.control.local_port); 
   9.301 +    }
   9.302 +    
   9.303 +    if (!RSP_RING_EMPTY) 
   9.304 +    {
   9.305 +        printf("nfy: rsp: %d\n", 
   9.306 +                RSP_RING_ENT(rsp_cons)->msg.u.control.local_port);
   9.307 +        return PyInt_FromLong(RSP_RING_ENT(rsp_cons)->msg.u.control.local_port); 
   9.308 +    }
   9.309 +    
   9.310 +    printf("nfy: returning None\n");
   9.311      Py_INCREF(Py_None);
   9.312      return Py_None;
   9.313  }
   9.314  
   9.315 +/* this is now a NOOP */
   9.316  static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
   9.317  {
   9.318 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.319 -    u16 v;
   9.320 -    int idx;
   9.321 +    Py_INCREF(Py_None);
   9.322 +    return Py_None;
   9.323 +}
   9.324  
   9.325 -    if ( !PyArg_ParseTuple(args, "i", &idx) )
   9.326 -        return NULL;
   9.327 -
   9.328 -    v = (u16)idx;
   9.329 -    
   9.330 -    (void)write(xun->evtchn_fd, &v, sizeof(v));
   9.331 -
   9.332 +/* this is now a NOOP */
   9.333 +static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
   9.334 +{
   9.335      Py_INCREF(Py_None);
   9.336      return Py_None;
   9.337  }
   9.338  
   9.339 -static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
   9.340 +static PyObject *xu_notifier_bind_virq(PyObject *self, 
   9.341 +            PyObject *args, PyObject *kwds)
   9.342  {
   9.343 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.344 -    int idx;
   9.345 +    int virq;
   9.346 +    xcs_msg_t kmsg;
   9.347  
   9.348 -    if ( !PyArg_ParseTuple(args, "i", &idx) )
   9.349 +    static char *kwd_list[] = { "virq", NULL };
   9.350 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
   9.351          return NULL;
   9.352 -
   9.353 -    if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
   9.354 -        return PyErr_SetFromErrno(PyExc_IOError);
   9.355 -
   9.356 -    Py_INCREF(Py_None);
   9.357 -    return Py_None;
   9.358 +    
   9.359 +    kmsg.type = XCS_VIRQ_BIND;
   9.360 +    kmsg.u.virq.virq  = virq;
   9.361 +    xcs_ctrl_send(&kmsg);
   9.362 +    xcs_ctrl_read(&kmsg);
   9.363 +    
   9.364 +    if ( kmsg.result != XCS_RSLT_OK )
   9.365 +    {  
   9.366 +        Py_INCREF(Py_None);
   9.367 +        return Py_None;
   9.368 +    }
   9.369 +    
   9.370 +    return PyInt_FromLong(kmsg.u.virq.port);
   9.371  }
   9.372  
   9.373 +static PyObject *xu_notifier_virq_send(PyObject *self, 
   9.374 +            PyObject *args, PyObject *kwds)
   9.375 +{
   9.376 +    int port;
   9.377 +    xcs_msg_t kmsg;
   9.378 +
   9.379 +    static char *kwd_list[] = { "port", NULL };
   9.380 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
   9.381 +        return NULL;
   9.382 +    
   9.383 +    kmsg.type = XCS_VIRQ;
   9.384 +    kmsg.u.control.local_port  = port;
   9.385 +    xcs_ctrl_send(&kmsg);
   9.386 +    xcs_ctrl_read(&kmsg);
   9.387 +    
   9.388 +    if ( kmsg.result != XCS_RSLT_OK )
   9.389 +    {  
   9.390 +        Py_INCREF(Py_None);
   9.391 +        return Py_None;
   9.392 +    }
   9.393 +    
   9.394 +    return PyInt_FromLong(kmsg.u.virq.port);
   9.395 +}
   9.396 +
   9.397 +/* this is now a NOOP */
   9.398  static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
   9.399  {
   9.400 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.401 -    int idx;
   9.402 -
   9.403 -    if ( !PyArg_ParseTuple(args, "i", &idx) )
   9.404 -        return NULL;
   9.405 -
   9.406 -    if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
   9.407 -        return PyErr_SetFromErrno(PyExc_IOError);
   9.408 -
   9.409      Py_INCREF(Py_None);
   9.410      return Py_None;
   9.411  }
   9.412  
   9.413  static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
   9.414  {
   9.415 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.416 -    return PyInt_FromLong(xun->evtchn_fd);
   9.417 +    return PyInt_FromLong(xcs_data_fd);
   9.418  }
   9.419  
   9.420  static PyMethodDef xu_notifier_methods[] = {
   9.421 @@ -178,6 +455,18 @@ static PyMethodDef xu_notifier_methods[]
   9.422        (PyCFunction)xu_notifier_unbind,
   9.423        METH_VARARGS,
   9.424        "No longer get notifications for a @port.\n" },
   9.425 +      
   9.426 +    { "bind_virq",
   9.427 +      (PyCFunction)xu_notifier_bind_virq,
   9.428 +      METH_VARARGS | METH_KEYWORDS,
   9.429 +      "Get notifications for a virq.\n" 
   9.430 +      " virq [int]: VIRQ to bind.\n\n" },
   9.431 +      
   9.432 +    { "virq_send",
   9.433 +      (PyCFunction)xu_notifier_virq_send,
   9.434 +      METH_VARARGS | METH_KEYWORDS,
   9.435 +      "Fire a virq notification.\n" 
   9.436 +      " port [int]: port that VIRQ is bound to.\n\n" },
   9.437  
   9.438      { "fileno", 
   9.439        (PyCFunction)xu_notifier_fileno,
   9.440 @@ -189,35 +478,23 @@ static PyMethodDef xu_notifier_methods[]
   9.441  
   9.442  staticforward PyTypeObject xu_notifier_type;
   9.443  
   9.444 +/* connect to xcs if we aren't already, and return a dummy object. */
   9.445  static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
   9.446  {
   9.447      xu_notifier_object *xun;
   9.448 -    struct stat st;
   9.449 +    int i;
   9.450  
   9.451 +printf("xu_notifier_new()\n");
   9.452      if ( !PyArg_ParseTuple(args, "") )
   9.453          return NULL;
   9.454  
   9.455      xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
   9.456  
   9.457 -    /* Make sure any existing device file links to correct device. */
   9.458 -    if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
   9.459 -         !S_ISCHR(st.st_mode) ||
   9.460 -         (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
   9.461 -        (void)unlink(EVTCHN_DEV_NAME);
   9.462 -
   9.463 - reopen:
   9.464 -    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
   9.465 -    if ( xun->evtchn_fd == -1 )
   9.466 -    {
   9.467 -        if ( (errno == ENOENT) &&
   9.468 -             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
   9.469 -             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
   9.470 -                    makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
   9.471 -            goto reopen;
   9.472 -        PyObject_Del((PyObject *)xun);
   9.473 -        return PyErr_SetFromErrno(PyExc_IOError);
   9.474 -    }
   9.475 -    set_cloexec(xun->evtchn_fd);
   9.476 +    for (i = 0; i < XCS_RING_SIZE; i++) 
   9.477 +        REQ_RING_ENT(i) = RSP_RING_ENT(i) = NULL;
   9.478 +    
   9.479 +    (void)xcs_connect("127.0.0.1", XCS_TCP_PORT);
   9.480 +    
   9.481  
   9.482      return (PyObject *)xun;
   9.483  }
   9.484 @@ -229,8 +506,6 @@ static PyObject *xu_notifier_getattr(PyO
   9.485  
   9.486  static void xu_notifier_dealloc(PyObject *self)
   9.487  {
   9.488 -    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.489 -    (void)close(xun->evtchn_fd);
   9.490      PyObject_Del(self);
   9.491  }
   9.492  
   9.493 @@ -696,43 +971,20 @@ static PyTypeObject xu_message_type = {
   9.494   * *********************** PORT ***********************
   9.495   */
   9.496  
   9.497 -static control_if_t *map_control_interface(int fd, unsigned long pfn,
   9.498 -					   u32 dom)
   9.499 -{
   9.500 -    char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
   9.501 -					PROT_READ|PROT_WRITE, pfn );
   9.502 -    if ( vaddr == NULL )
   9.503 -        return NULL;
   9.504 -    return (control_if_t *)(vaddr + 2048);
   9.505 -}
   9.506 -static void unmap_control_interface(int fd, control_if_t *c)
   9.507 -{
   9.508 -    char *vaddr = (char *)c - 2048;
   9.509 -    (void)munmap(vaddr, PAGE_SIZE);
   9.510 -}
   9.511 -
   9.512  typedef struct xu_port_object {
   9.513      PyObject_HEAD;
   9.514      int xc_handle;
   9.515      int connected;
   9.516      u32 remote_dom;
   9.517      int local_port, remote_port;
   9.518 -    control_if_t    *interface;
   9.519 -    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
   9.520 -    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
   9.521 +    struct xu_port_object *fix_next;
   9.522  } xu_port_object;
   9.523  
   9.524  static PyObject *port_error;
   9.525  
   9.526 +/* now a NOOP */
   9.527  static PyObject *xu_port_notify(PyObject *self, PyObject *args)
   9.528  {
   9.529 -    xu_port_object *xup = (xu_port_object *)self;
   9.530 -
   9.531 -    if ( !PyArg_ParseTuple(args, "") )
   9.532 -        return NULL;
   9.533 -
   9.534 -    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
   9.535 -
   9.536      Py_INCREF(Py_None);
   9.537      return Py_None;
   9.538  }
   9.539 @@ -741,39 +993,119 @@ static PyObject *xu_port_read_request(Py
   9.540  {
   9.541      xu_port_object    *xup = (xu_port_object *)self;
   9.542      xu_message_object *xum;
   9.543 -    CONTROL_RING_IDX   c = xup->tx_req_cons;
   9.544 -    control_if_t      *cif = xup->interface;
   9.545      control_msg_t     *cmsg;
   9.546 -
   9.547 -    if ( !PyArg_ParseTuple(args, "") )
   9.548 -        return NULL;
   9.549 +    unsigned          i;
   9.550 +    xcs_msg_ent_t    *ent = NULL;
   9.551 +    
   9.552 +    for ( i = req_cons; (i != req_prod); i++ ) {
   9.553 +        ent = REQ_RING_ENT(i);
   9.554 +        if (ent == NULL) 
   9.555 +            continue;
   9.556 +        if (ent->msg.u.control.remote_dom == xup->remote_dom)
   9.557 +            break;
   9.558 +    }
   9.559 +    
   9.560 +    if ((ent == NULL) ||
   9.561 +        (ent->msg.u.control.remote_dom != xup->remote_dom)) 
   9.562 +        goto none;
   9.563 +    
   9.564 +printf("read request (%d:%d)\n", ent->msg.u.control.msg.type, 
   9.565 +        ent->msg.u.control.msg.subtype);
   9.566  
   9.567 -    if ( (c == cif->tx_req_prod) || 
   9.568 -         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
   9.569 -    {
   9.570 -        PyErr_SetString(port_error, "no request to read");
   9.571 -        return NULL;
   9.572 -    }
   9.573 -
   9.574 -    /* Need to ensure we see the request, despite seeing the index update.*/
   9.575 -    rmb();
   9.576 -
   9.577 -    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
   9.578 +    cmsg = &ent->msg.u.control.msg;
   9.579      xum = PyObject_New(xu_message_object, &xu_message_type);
   9.580      memcpy(&xum->msg, cmsg, sizeof(*cmsg));
   9.581      if ( xum->msg.length > sizeof(xum->msg.msg) )
   9.582          xum->msg.length = sizeof(xum->msg.msg);
   9.583 -    xup->tx_req_cons++;
   9.584 +    free(ent);
   9.585 +    
   9.586 +    /* remove the entry from the ring and advance the consumer if possible */
   9.587 +    REQ_RING_ENT(i) = NULL;
   9.588 +    while ( (REQ_RING_ENT(req_cons) == NULL) && (!REQ_RING_EMPTY) )
   9.589 +        req_cons++;
   9.590 +    
   9.591      return (PyObject *)xum;
   9.592 +    
   9.593 +none:
   9.594 +printf("read request - NO REQUEST!\n");
   9.595 +    Py_INCREF(Py_None);
   9.596 +    return Py_None;
   9.597 +    
   9.598  }
   9.599  
   9.600  static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
   9.601  {
   9.602      xu_port_object    *xup = (xu_port_object *)self;
   9.603      xu_message_object *xum;
   9.604 -    CONTROL_RING_IDX   p = xup->rx_req_prod;
   9.605 -    control_if_t      *cif = xup->interface;
   9.606 +    xcs_msg_t          kmsg;
   9.607 +
   9.608 +    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
   9.609 +        return NULL;
   9.610 +
   9.611 +    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
   9.612 +    {
   9.613 +        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
   9.614 +        return NULL;        
   9.615 +    }
   9.616 +
   9.617 +    kmsg.type = XCS_REQUEST;
   9.618 +    kmsg.u.control.remote_dom = xup->remote_dom;
   9.619 +    memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
   9.620 +    xcs_data_send(&kmsg);
   9.621 +    
   9.622 +    Py_INCREF(Py_None);
   9.623 +    return Py_None;
   9.624 +}
   9.625 +
   9.626 +static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
   9.627 +{
   9.628 +    xu_port_object    *xup = (xu_port_object *)self;
   9.629 +    xu_message_object *xum;
   9.630      control_msg_t     *cmsg;
   9.631 +    unsigned          i;
   9.632 +    xcs_msg_ent_t    *ent = NULL;
   9.633 +    
   9.634 +    for ( i = rsp_cons; (i != rsp_prod); i++ ) {
   9.635 +        ent = RSP_RING_ENT(i);
   9.636 +        if (ent == NULL) 
   9.637 +            continue;
   9.638 +        if (ent->msg.u.control.remote_dom == xup->remote_dom)
   9.639 +            break;
   9.640 +    }
   9.641 +    
   9.642 +    if ((ent == NULL) ||
   9.643 +        (ent->msg.u.control.remote_dom != xup->remote_dom))
   9.644 +         goto none;
   9.645 +    
   9.646 +printf("read response (%d:%d)\n", ent->msg.u.control.msg.type, 
   9.647 +        ent->msg.u.control.msg.subtype);
   9.648 +
   9.649 +    cmsg = &ent->msg.u.control.msg;
   9.650 +    xum = PyObject_New(xu_message_object, &xu_message_type);
   9.651 +    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
   9.652 +    if ( xum->msg.length > sizeof(xum->msg.msg) )
   9.653 +        xum->msg.length = sizeof(xum->msg.msg);
   9.654 +    free(ent);
   9.655 +    
   9.656 +    /* remove the entry from the ring and advance the consumer if possible */
   9.657 +    RSP_RING_ENT(i) = NULL;
   9.658 +    while ( (RSP_RING_ENT(rsp_cons) == NULL) && (!RSP_RING_EMPTY) )
   9.659 +        rsp_cons++;
   9.660 +    
   9.661 +    return (PyObject *)xum;
   9.662 +    
   9.663 +none:
   9.664 +printf("read response - NO RESPONSE!\n");
   9.665 +    Py_INCREF(Py_None);
   9.666 +    return Py_None;
   9.667 +    
   9.668 +}
   9.669 +
   9.670 +static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
   9.671 +{
   9.672 +    xu_port_object    *xup = (xu_port_object *)self;
   9.673 +    xu_message_object *xum;
   9.674 +    xcs_msg_t          kmsg;
   9.675  
   9.676      if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
   9.677          return NULL;
   9.678 @@ -784,79 +1116,10 @@ static PyObject *xu_port_write_request(P
   9.679          return NULL;        
   9.680      }
   9.681  
   9.682 -    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
   9.683 -    {
   9.684 -        PyErr_SetString(port_error, "no space to write request");
   9.685 -        return NULL;
   9.686 -    }
   9.687 -
   9.688 -    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
   9.689 -    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
   9.690 -
   9.691 -    wmb();
   9.692 -    xup->rx_req_prod = cif->rx_req_prod = p + 1;
   9.693 -
   9.694 -    Py_INCREF(Py_None);
   9.695 -    return Py_None;
   9.696 -}
   9.697 -
   9.698 -static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
   9.699 -{
   9.700 -    xu_port_object    *xup = (xu_port_object *)self;
   9.701 -    xu_message_object *xum;
   9.702 -    CONTROL_RING_IDX   c = xup->rx_resp_cons;
   9.703 -    control_if_t      *cif = xup->interface;
   9.704 -    control_msg_t     *cmsg;
   9.705 -
   9.706 -    if ( !PyArg_ParseTuple(args, "") )
   9.707 -        return NULL;
   9.708 -
   9.709 -    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
   9.710 -    {
   9.711 -        PyErr_SetString(port_error, "no response to read");
   9.712 -        return NULL;
   9.713 -    }
   9.714 -
   9.715 -    /* Need to ensure we see the response, despite seeing the index update.*/
   9.716 -    rmb();
   9.717 -
   9.718 -    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
   9.719 -    xum = PyObject_New(xu_message_object, &xu_message_type);
   9.720 -    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
   9.721 -    if ( xum->msg.length > sizeof(xum->msg.msg) )
   9.722 -        xum->msg.length = sizeof(xum->msg.msg);
   9.723 -    xup->rx_resp_cons++;
   9.724 -    return (PyObject *)xum;
   9.725 -}
   9.726 -
   9.727 -static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
   9.728 -{
   9.729 -    xu_port_object    *xup = (xu_port_object *)self;
   9.730 -    xu_message_object *xum;
   9.731 -    CONTROL_RING_IDX   p = xup->tx_resp_prod;
   9.732 -    control_if_t      *cif = xup->interface;
   9.733 -    control_msg_t     *cmsg;
   9.734 -
   9.735 -    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
   9.736 -        return NULL;
   9.737 -
   9.738 -    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
   9.739 -    {
   9.740 -        PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
   9.741 -        return NULL;        
   9.742 -    }
   9.743 -
   9.744 -    if ( p == xup->tx_req_cons )
   9.745 -    {
   9.746 -        PyErr_SetString(port_error, "no space to write response");
   9.747 -        return NULL;
   9.748 -    }
   9.749 -
   9.750 -    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
   9.751 -    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
   9.752 -
   9.753 -    wmb();
   9.754 -    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
   9.755 +    kmsg.type = XCS_RESPONSE;
   9.756 +    kmsg.u.control.remote_dom = xup->remote_dom;
   9.757 +    memcpy(&kmsg.u.control.msg, &xum->msg, sizeof(control_msg_t));
   9.758 +    xcs_data_send(&kmsg);
   9.759  
   9.760      Py_INCREF(Py_None);
   9.761      return Py_None;
   9.762 @@ -864,133 +1127,141 @@ static PyObject *xu_port_write_response(
   9.763  
   9.764  static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
   9.765  {
   9.766 -    xu_port_object    *xup = (xu_port_object *)self;
   9.767 -    CONTROL_RING_IDX   c = xup->tx_req_cons;
   9.768 -    control_if_t      *cif = xup->interface;
   9.769 +    xu_port_object   *xup = (xu_port_object *)self;
   9.770 +    xcs_msg_ent_t    *ent;
   9.771 +    int               found = 0;
   9.772 +    unsigned          i;
   9.773  
   9.774 +printf("xu_port_request_to_read()\n");    
   9.775      if ( !PyArg_ParseTuple(args, "") )
   9.776          return NULL;
   9.777  
   9.778 -    if ( (c == cif->tx_req_prod) || 
   9.779 -         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
   9.780 -        return PyInt_FromLong(0);
   9.781 -
   9.782 -    return PyInt_FromLong(1);
   9.783 +    for ( i = req_cons; (i != req_prod); i++ ) {
   9.784 +        ent = REQ_RING_ENT(i);
   9.785 +        if (ent == NULL) 
   9.786 +            continue;
   9.787 +        if (ent->msg.u.control.remote_dom == xup->remote_dom) {
   9.788 +            found = 1;
   9.789 +            break;
   9.790 +        }
   9.791 +    }
   9.792 +    
   9.793 +    return PyInt_FromLong(found);
   9.794  }
   9.795  
   9.796  static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
   9.797  {
   9.798 -    xu_port_object    *xup = (xu_port_object *)self;
   9.799 -    CONTROL_RING_IDX   p = xup->rx_req_prod;
   9.800 -
   9.801      if ( !PyArg_ParseTuple(args, "") )
   9.802          return NULL;
   9.803  
   9.804 -    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
   9.805 -        return PyInt_FromLong(0);
   9.806 -
   9.807      return PyInt_FromLong(1);
   9.808  }
   9.809  
   9.810  static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
   9.811  {
   9.812 -    xu_port_object    *xup = (xu_port_object *)self;
   9.813 -    CONTROL_RING_IDX   c = xup->rx_resp_cons;
   9.814 -    control_if_t      *cif = xup->interface;
   9.815 +    xu_port_object   *xup = (xu_port_object *)self;
   9.816 +    xcs_msg_ent_t    *ent;
   9.817 +    int               found = 0;
   9.818 +    unsigned          i;
   9.819  
   9.820 +printf("xu_port_response_to_read()\n");    
   9.821      if ( !PyArg_ParseTuple(args, "") )
   9.822          return NULL;
   9.823  
   9.824 -    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
   9.825 -        return PyInt_FromLong(0);
   9.826 -
   9.827 -    return PyInt_FromLong(1);
   9.828 +    for ( i = rsp_cons; (i != rsp_prod); i++ ) {
   9.829 +        ent = RSP_RING_ENT(i);
   9.830 +        if (ent == NULL) 
   9.831 +            continue;
   9.832 +        if (ent->msg.u.control.remote_dom == xup->remote_dom) {
   9.833 +            found = 1;
   9.834 +            break;
   9.835 +        }
   9.836 +    }
   9.837 +    
   9.838 +    return PyInt_FromLong(found);
   9.839  }
   9.840  
   9.841  static PyObject *xu_port_space_to_write_response(
   9.842      PyObject *self, PyObject *args)
   9.843  {
   9.844 -    xu_port_object    *xup = (xu_port_object *)self;
   9.845 -    CONTROL_RING_IDX   p = xup->tx_resp_prod;
   9.846 -
   9.847      if ( !PyArg_ParseTuple(args, "") )
   9.848          return NULL;
   9.849  
   9.850 -    if ( p == xup->tx_req_cons )
   9.851 -        return PyInt_FromLong(0);
   9.852 -
   9.853      return PyInt_FromLong(1);
   9.854  }
   9.855  
   9.856 -static int __xu_port_connect(xu_port_object *xup)
   9.857 +/* NOOP */
   9.858 +static PyObject *xu_port_connect(PyObject *self, PyObject *args)
   9.859  {
   9.860 -    xc_dominfo_t info;
   9.861 -
   9.862 -    if ( xup->connected )
   9.863 -    {
   9.864 -	return 0;
   9.865 -    }
   9.866 -
   9.867 -    if ( (xc_domain_getinfo(xup->xc_handle, xup->remote_dom, 1, &info) != 1) ||
   9.868 -         (info.domid != xup->remote_dom) )
   9.869 -    {
   9.870 -        PyErr_SetString(port_error, "Failed to obtain domain status");
   9.871 -        return -1;
   9.872 -    }
   9.873 -
   9.874 -    xup->interface = 
   9.875 -        map_control_interface(xup->xc_handle, info.shared_info_frame,
   9.876 -			      xup->remote_dom);
   9.877 -
   9.878 -    if ( xup->interface == NULL )
   9.879 -    {
   9.880 -        PyErr_SetString(port_error, "Failed to map domain control interface");
   9.881 -        return -1;
   9.882 -    }
   9.883 -
   9.884 -    /* Synchronise ring indexes. */
   9.885 -    xup->tx_resp_prod = xup->interface->tx_resp_prod;
   9.886 -    xup->tx_req_cons  = xup->interface->tx_resp_prod;
   9.887 -    xup->rx_req_prod  = xup->interface->rx_req_prod;
   9.888 -    xup->rx_resp_cons = xup->interface->rx_resp_prod;
   9.889 -
   9.890 -    xup->connected = 1;
   9.891 -
   9.892 -    return 0;
   9.893 +    Py_INCREF(Py_None);
   9.894 +    return Py_None;
   9.895  }
   9.896  
   9.897 -static void __xu_port_disconnect(xu_port_object *xup)
   9.898 -{
   9.899 -    if ( xup->connected )
   9.900 -	unmap_control_interface(xup->xc_handle, xup->interface);
   9.901 -    xup->connected = 0;
   9.902 -}
   9.903 -
   9.904 -static PyObject *xu_port_connect(PyObject *self, PyObject *args)
   9.905 +/* NOOP */
   9.906 +static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
   9.907  {
   9.908 -    xu_port_object *xup = (xu_port_object *)self;
   9.909 -
   9.910 -    if ( !PyArg_ParseTuple(args, "") )
   9.911 -        return NULL;
   9.912 -
   9.913 -    if ( __xu_port_connect(xup) != 0 )
   9.914 -        return NULL;
   9.915 -
   9.916      Py_INCREF(Py_None);
   9.917      return Py_None;
   9.918  }
   9.919  
   9.920 -static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
   9.921 +static PyObject *xu_port_register(PyObject *self, PyObject *args, 
   9.922 +        PyObject *kwds)
   9.923  {
   9.924 -    xu_port_object *xup = (xu_port_object *)self;
   9.925 +    int type;
   9.926 +    xcs_msg_t msg;
   9.927 +    xu_port_object   *xup = (xu_port_object *)self;
   9.928 +    static char *kwd_list[] = { "type", NULL };
   9.929  
   9.930 -    if ( !PyArg_ParseTuple(args, "") )
   9.931 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
   9.932 +                                      &type) )
   9.933          return NULL;
   9.934 -
   9.935 -    __xu_port_disconnect(xup);
   9.936 +    
   9.937 +    printf("REGISTER  : Dom: %3d  Port: %3d  Type:%3d\n",
   9.938 +        xup->remote_dom, xup->local_port, type);
   9.939 +    
   9.940 +    msg.type = XCS_MSG_BIND;
   9.941 +    msg.u.bind.port = xup->local_port;
   9.942 +    msg.u.bind.type = type;
   9.943 +    xcs_ctrl_send(&msg);
   9.944 +    xcs_ctrl_read(&msg);
   9.945 +    
   9.946 +    if (msg.result != XCS_RSLT_OK)
   9.947 +    {
   9.948 +        printf("          : REGISTRATION FAILED! (%d)\n", msg.result);
   9.949 +        return PyInt_FromLong(0);
   9.950 +    }
   9.951 +    
   9.952 +    return PyInt_FromLong(1);        
   9.953 +}
   9.954  
   9.955 -    Py_INCREF(Py_None);
   9.956 -    return Py_None;
   9.957 +static PyObject *xu_port_deregister(PyObject *self, PyObject *args,
   9.958 +        PyObject *kwds)
   9.959 +{
   9.960 +    int type;
   9.961 +    xcs_msg_t msg;
   9.962 +    xu_port_object   *xup = (xu_port_object *)self;
   9.963 +    static char *kwd_list[] = { "type", NULL };
   9.964 +
   9.965 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
   9.966 +                                      &type) )
   9.967 +        return NULL;
   9.968 +    
   9.969 +    printf("DEREGISTER: Dom: %3d  Port: %3d  Type:%3d\n",
   9.970 +        xup->remote_dom, xup->local_port, type);
   9.971 +    
   9.972 +    msg.type = XCS_MSG_UNBIND;
   9.973 +    msg.u.bind.port = xup->local_port;
   9.974 +    msg.u.bind.type = type;
   9.975 +    xcs_ctrl_send(&msg);
   9.976 +    xcs_ctrl_read(&msg);
   9.977 +    
   9.978 +    if (msg.result != XCS_RSLT_OK)
   9.979 +    {
   9.980 +        printf("          : DEREGISTRATION FAILED! (%d)\n", msg.result);
   9.981 +        return PyInt_FromLong(0);
   9.982 +    }
   9.983 +    
   9.984 +    return PyInt_FromLong(1);        
   9.985  }
   9.986  
   9.987  static PyMethodDef xu_port_methods[] = {
   9.988 @@ -1038,6 +1309,16 @@ static PyMethodDef xu_port_methods[] = {
   9.989        (PyCFunction)xu_port_space_to_write_response,
   9.990        METH_VARARGS,
   9.991        "Returns TRUE if there is space to write a response message.\n" },
   9.992 +      
   9.993 +    { "register",
   9.994 +      (PyCFunction)xu_port_register,
   9.995 +      METH_VARARGS | METH_KEYWORDS,
   9.996 +      "Register to receive a type of message on this channel.\n" },
   9.997 +      
   9.998 +    { "deregister",
   9.999 +      (PyCFunction)xu_port_deregister,
  9.1000 +      METH_VARARGS | METH_KEYWORDS,
  9.1001 +      "Stop receiving a type of message on this port.\n" },
  9.1002  
  9.1003      { "connect",
  9.1004        (PyCFunction)xu_port_connect,
  9.1005 @@ -1059,6 +1340,7 @@ static PyObject *xu_port_new(PyObject *s
  9.1006      xu_port_object *xup;
  9.1007      u32 dom;
  9.1008      int port1 = 0, port2 = 0;
  9.1009 +    xcs_msg_t kmsg;
  9.1010  
  9.1011      static char *kwd_list[] = { "dom", "local_port", "remote_port", NULL };
  9.1012  
  9.1013 @@ -1070,51 +1352,26 @@ static PyObject *xu_port_new(PyObject *s
  9.1014  
  9.1015      xup->connected  = 0;
  9.1016      xup->remote_dom = dom;
  9.1017 -
  9.1018 -    if ( (xup->xc_handle = xc_interface_open()) == -1 )
  9.1019 -    {
  9.1020 -        PyErr_SetString(port_error, "Could not open Xen control interface");
  9.1021 +    
  9.1022 +    kmsg.type = XCS_CIF_NEW_CC;
  9.1023 +    kmsg.u.interface.dom         = xup->remote_dom;
  9.1024 +    kmsg.u.interface.local_port  = port1; 
  9.1025 +    kmsg.u.interface.remote_port = port2;
  9.1026 +    xcs_ctrl_send(&kmsg);
  9.1027 +    xcs_ctrl_read(&kmsg);
  9.1028 +    
  9.1029 +    if ( kmsg.result != XCS_RSLT_OK ) 
  9.1030          goto fail1;
  9.1031 -    }
  9.1032 +        
  9.1033 +    xup->local_port  = kmsg.u.interface.local_port;
  9.1034 +    xup->remote_port = kmsg.u.interface.remote_port;
  9.1035 +    xup->connected = 1;
  9.1036 +                
  9.1037 +    return (PyObject *)xup;
  9.1038  
  9.1039 -    if ( dom == 0 )
  9.1040 -    {
  9.1041 -        /*
  9.1042 -         * The control-interface event channel for DOM0 is already set up.
  9.1043 -         * We use an ioctl to discover the port at our end of the channel.
  9.1044 -         */
  9.1045 -        port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
  9.1046 -        port2 = -1; /* We don't need the remote end of the DOM0 link. */
  9.1047 -        if ( port1 < 0 )
  9.1048 -        {
  9.1049 -            PyErr_SetString(port_error, "Could not open channel to DOM0");
  9.1050 -            goto fail2;
  9.1051 -        }
  9.1052 -    }
  9.1053 -    else if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
  9.1054 -                                         DOMID_SELF, dom, 
  9.1055 -                                         &port1, &port2) != 0 )
  9.1056 -    {
  9.1057 -        PyErr_SetString(port_error, "Could not open channel to domain");
  9.1058 -        goto fail2;
  9.1059 -    }
  9.1060 -
  9.1061 -    xup->local_port  = port1;
  9.1062 -    xup->remote_port = port2;
  9.1063 -
  9.1064 -    if ( __xu_port_connect(xup) != 0 )
  9.1065 -        goto fail3;
  9.1066 -
  9.1067 -    return (PyObject *)xup;
  9.1068 -    
  9.1069 - fail3:
  9.1070 -    if ( dom != 0 )
  9.1071 -        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
  9.1072 - fail2:
  9.1073 -    (void)xc_interface_close(xup->xc_handle);
  9.1074   fail1:
  9.1075      PyObject_Del((PyObject *)xup);
  9.1076 -    return NULL;        
  9.1077 +    return NULL;    
  9.1078  }
  9.1079  
  9.1080  static PyObject *xu_port_getattr(PyObject *obj, char *name)
  9.1081 @@ -1131,11 +1388,20 @@ static PyObject *xu_port_getattr(PyObjec
  9.1082  
  9.1083  static void xu_port_dealloc(PyObject *self)
  9.1084  {
  9.1085 +
  9.1086      xu_port_object *xup = (xu_port_object *)self;
  9.1087 -    __xu_port_disconnect(xup);
  9.1088 +    xcs_msg_t kmsg;
  9.1089 +
  9.1090      if ( xup->remote_dom != 0 )
  9.1091 -        (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
  9.1092 -    (void)xc_interface_close(xup->xc_handle);
  9.1093 +    {  
  9.1094 +        kmsg.type = XCS_CIF_FREE_CC;
  9.1095 +        kmsg.u.interface.dom         = xup->remote_dom;
  9.1096 +        kmsg.u.interface.local_port  = xup->local_port; 
  9.1097 +        kmsg.u.interface.remote_port = xup->remote_port;
  9.1098 +        xcs_ctrl_send(&kmsg);
  9.1099 +        xcs_ctrl_read(&kmsg);
  9.1100 +    }
  9.1101 +            
  9.1102      PyObject_Del(self);
  9.1103  }
  9.1104  
    10.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Fri Dec 31 13:53:32 2004 +0000
    10.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Fri Dec 31 17:26:00 2004 +0000
    10.3 @@ -118,9 +118,9 @@ class NotifierPort(abstract.FileDescript
    10.4          if hasattr(self, 'protocol'):
    10.5              self.protocol.doStop()
    10.6          self.connected = 0
    10.7 -        #self.notifier.close() # Not implemented.
    10.8 -        os.close(self.fileno())
    10.9 -        del self.notifier
   10.10 +        #self.notifier.close()   # (this said:) Not implemented.
   10.11 +        #os.close(self.fileno()) # But yes it is...
   10.12 +        del self.notifier        # ...as _dealloc!
   10.13          if hasattr(self, 'd'):
   10.14              self.d.callback(None)
   10.15              del self.d
    11.1 --- a/tools/python/xen/xend/server/channel.py	Fri Dec 31 13:53:32 2004 +0000
    11.2 +++ b/tools/python/xen/xend/server/channel.py	Fri Dec 31 17:26:00 2004 +0000
    11.3 @@ -171,8 +171,10 @@ class VirqChannel(BaseChannel):
    11.4          """
    11.5          BaseChannel.__init__(self, factory)
    11.6          self.virq = virq
    11.7 +        self.factory = factory
    11.8          # Notification port (int).
    11.9 -        self.port = xc.evtchn_bind_virq(virq)
   11.10 +        #self.port = xc.evtchn_bind_virq(virq)
   11.11 +        self.port = factory.notifier.bind_virq(virq)
   11.12          self.idx = self.port
   11.13          # Clients to call when a virq arrives.
   11.14          self.clients = []
   11.15 @@ -208,7 +210,8 @@ class VirqChannel(BaseChannel):
   11.16              c.virqReceived(self.virq)
   11.17  
   11.18      def notify(self):
   11.19 -        xc.evtchn_send(self.port)
   11.20 +        # xc.evtchn_send(self.port)
   11.21 +        self.factory.notifier.virq_send(self.port)
   11.22  
   11.23  
   11.24  class Channel(BaseChannel):
   11.25 @@ -279,6 +282,7 @@ class Channel(BaseChannel):
   11.26          self.devs.append(dev)
   11.27          for ty in types:
   11.28              self.devs_by_type[ty] = dev
   11.29 +        self.port.register(ty)
   11.30  
   11.31      def deregisterDevice(self, dev):
   11.32          """Remove the registration for a device controller.
   11.33 @@ -290,6 +294,7 @@ class Channel(BaseChannel):
   11.34          types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
   11.35          for ty in types:
   11.36              del self.devs_by_type[ty]
   11.37 +            self.port.deregister(ty)
   11.38  
   11.39      def getDevice(self, type):
   11.40          """Get the device controller handling a message type.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/xcs/Makefile	Fri Dec 31 17:26:00 2004 +0000
    12.3 @@ -0,0 +1,44 @@
    12.4 +# Makefile for XCS
    12.5 +# Andrew Warfield, 2004
    12.6 +
    12.7 +XEN_ROOT=../..
    12.8 +include $(XEN_ROOT)/tools/Make.defs
    12.9 +
   12.10 +XCS_INSTALL_DIR = /usr/sbin
   12.11 +
   12.12 +CC       = gcc
   12.13 +CFLAGS   = -Wall -Werror -g3 -D _XOPEN_SOURCE=600
   12.14 +
   12.15 +CFLAGS  += -I $(XEN_XC)
   12.16 +CFLAGS  += -I $(XEN_LIBXC)
   12.17 +CFLAGS  += -I $(XEN_LIBXUTIL)
   12.18 +
   12.19 +SRCS    :=
   12.20 +SRCS    += ctrl_interface.c
   12.21 +SRCS    += bindings.c
   12.22 +SRCS    += connection.c
   12.23 +SRCS    += evtchn.c
   12.24 +SRCS    += xcs.c
   12.25 +
   12.26 +HDRS     = $(wildcard *.h)
   12.27 +OBJS     = $(patsubst %.c,%.o,$(SRCS))
   12.28 +BIN      = xcs
   12.29 +
   12.30 +all: $(BIN) xcsdump
   12.31 +
   12.32 +clean:
   12.33 +	$(RM) *.a *.so *.o *.rpm $(BIN) ctrl_dump
   12.34 +
   12.35 +xcsdump: xcsdump.c
   12.36 +	$(CC) $(CFLAGS) -o xcsdump xcsdump.c -L$(XEN_LIBXC) -L$(XEN_LIBXUTIL) \
   12.37 +              ctrl_interface.c evtchn.c  -lxc -lxutil
   12.38 +
   12.39 +$(BIN): $(OBJS)
   12.40 +	$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_LIBXUTIL) -lxc -lxutil 
   12.41 +
   12.42 +install: xcs xcsdump
   12.43 +	mkdir -p $(prefix)/$(XCS_INSTALL_DIR)
   12.44 +	mkdir -p $(prefix)/usr/include
   12.45 +	install -m0755 xcs $(prefix)/$(XCS_INSTALL_DIR)
   12.46 +	install -m0755 xcsdump $(prefix)/$(XCS_INSTALL_DIR)
   12.47 +	install -m0644 xcs_proto.h $(prefix)/usr/include
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/xcs/bindings.c	Fri Dec 31 17:26:00 2004 +0000
    13.3 @@ -0,0 +1,179 @@
    13.4 +/* bindings.c
    13.5 + *
    13.6 + * Manage subscriptions for the control interface switch.
    13.7 + *
    13.8 + * (c) 2004, Andrew Warfield
    13.9 + *
   13.10 + */
   13.11 +
   13.12 +/* Interfaces:
   13.13 + *
   13.14 + * xcs_bind   (port, type, connection)
   13.15 + *   - Register connection to receive messages of this type.
   13.16 + * xcs_unbind (port, type, connection)
   13.17 + *   - Remove an existing registration. (Must be an exact match)
   13.18 + * xcs_lookup (port, type)
   13.19 + *   - Return a list of connections matching a registration.
   13.20 + * 
   13.21 + * - All connections have a connection.bindings list of current bindings.
   13.22 + * - (port, type) pairs may be wildcarded with -1.
   13.23 + */
   13.24 + 
   13.25 +#include <stdio.h>
   13.26 +#include <stdlib.h> 
   13.27 +#include <errno.h>
   13.28 +#include <string.h>
   13.29 +#include "xcs.h"
   13.30 +
   13.31 +
   13.32 +typedef struct binding_ent_st {
   13.33 +    connection_t          *con;
   13.34 +    struct binding_ent_st *next;
   13.35 +} binding_ent_t;
   13.36 +
   13.37 +#define BINDING_TABLE_SIZE       1024
   13.38 +
   13.39 +static binding_ent_t *binding_table[BINDING_TABLE_SIZE];
   13.40 +        
   13.41 +#define PORT_WILD(_ent) ((_ent)->port == PORT_WILDCARD)
   13.42 +#define TYPE_WILD(_ent) ((_ent)->type == TYPE_WILDCARD)
   13.43 +#define FULLY_WILD(_ent) (PORT_WILD(_ent) && TYPE_WILD(_ent))
   13.44 +
   13.45 +#define BINDING_HASH(_key) \
   13.46 +    ((((_key)->port * 11) ^ (_key)->type) % BINDING_TABLE_SIZE)
   13.47 +    
   13.48 +    
   13.49 +void init_bindings(void)
   13.50 +{
   13.51 +    memset(binding_table, 0, sizeof(binding_table));
   13.52 +}
   13.53 +
   13.54 +static int table_add(binding_ent_t *table[],
   13.55 +                            connection_t *con, 
   13.56 +                            binding_key_t *key)
   13.57 +{
   13.58 +    binding_ent_t **curs, *ent;
   13.59 +        
   13.60 +    curs = &table[BINDING_HASH(key)];
   13.61 +    
   13.62 +    while (*curs != NULL) {
   13.63 +        if ((*curs)->con == con) {
   13.64 +            DPRINTF("Tried to add an ent that already existed.\n");
   13.65 +            goto done;
   13.66 +        }
   13.67 +        curs = &(*curs)->next;
   13.68 +    }
   13.69 +    
   13.70 +    if (connection_add_binding(con, key) != 0)
   13.71 +    {
   13.72 +       DPRINTF("couldn't add binding on connection (%lu)\n", con->id);
   13.73 +       goto fail;
   13.74 +    }
   13.75 +    ent = (binding_ent_t *)malloc(sizeof(binding_ent_t));
   13.76 +    if (ent == 0) {
   13.77 +       DPRINTF("couldn't alloc binding ent!\n");
   13.78 +       goto fail;
   13.79 +    }
   13.80 +    ent->con = con;
   13.81 +    ent->next = NULL;
   13.82 +    *curs = ent;
   13.83 +    
   13.84 +done:
   13.85 +    return 0;
   13.86 +
   13.87 +fail:
   13.88 +    return -1;
   13.89 +}
   13.90 +
   13.91 +
   13.92 +static inline int binding_has_colliding_hashes(connection_t *con, 
   13.93 +                                               binding_key_t *key)
   13.94 +{
   13.95 +    int hash, count = 0;
   13.96 +    binding_key_ent_t *ent;
   13.97 +    
   13.98 +    ent = con->bindings; 
   13.99 +    hash = BINDING_HASH(key);
  13.100 +    
  13.101 +    while (ent != NULL) {
  13.102 +        if (BINDING_HASH(&ent->key) == hash) count ++;
  13.103 +        ent = ent->next;
  13.104 +    }
  13.105 +    
  13.106 +    return (count > 1);
  13.107 +}
  13.108 +static int table_remove(binding_ent_t *table[],
  13.109 +                            connection_t *con, 
  13.110 +                            binding_key_t *key)
  13.111 +{
  13.112 +    binding_ent_t **curs, *ent;
  13.113 +    
  13.114 +    if (!binding_has_colliding_hashes(con, key))
  13.115 +    {
  13.116 +    
  13.117 +        curs = &table[BINDING_HASH(key)];
  13.118 +
  13.119 +        while ((*curs != NULL) && ((*curs)->con != con))
  13.120 +           curs = &(*curs)->next;
  13.121 +
  13.122 +        if (*curs != NULL) {
  13.123 +           ent = *curs;
  13.124 +           *curs = (*curs)->next;
  13.125 +           free(ent);
  13.126 +        }
  13.127 +    }
  13.128 +    
  13.129 +    connection_remove_binding(con, key);
  13.130 +    
  13.131 +    return 0;    
  13.132 +}
  13.133 +
  13.134 +int xcs_bind(connection_t *con, int port, u16 type)
  13.135 +{
  13.136 +    binding_key_t  key;
  13.137 +    
  13.138 +    key.port = port;
  13.139 +    key.type = type;
  13.140 +    
  13.141 +    return table_add(binding_table, con, &key);  
  13.142 +}
  13.143 +
  13.144 +int xcs_unbind(connection_t *con, int port, u16 type)
  13.145 +{
  13.146 +    binding_key_t  key;
  13.147 +    
  13.148 +    key.port = port;
  13.149 +    key.type = type;
  13.150 +    
  13.151 +    return table_remove(binding_table, con, &key); 
  13.152 +}
  13.153 +
  13.154 +
  13.155 +static void for_each_binding(binding_ent_t *list, binding_key_t *key, 
  13.156 +                void (*f)(connection_t *, void *), void *arg)
  13.157 +{
  13.158 +    while (list != NULL) 
  13.159 +    {
  13.160 +        if (connection_has_binding(list->con, key))
  13.161 +            f(list->con, arg);
  13.162 +        list = list->next;
  13.163 +    }  
  13.164 +}
  13.165 +
  13.166 +void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *), 
  13.167 +                void *arg)
  13.168 +{
  13.169 +    binding_key_t  key;
  13.170 +            
  13.171 +    key.port  = port; key.type = type;
  13.172 +    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
  13.173 +            
  13.174 +    key.port  = port; key.type = TYPE_WILDCARD;
  13.175 +    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
  13.176 +            
  13.177 +    key.port  = PORT_WILDCARD; key.type = type;
  13.178 +    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
  13.179 +            
  13.180 +    key.port  = PORT_WILDCARD; key.type = TYPE_WILDCARD;
  13.181 +    for_each_binding(binding_table[BINDING_HASH(&key)], &key, f, arg);
  13.182 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/xcs/connection.c	Fri Dec 31 17:26:00 2004 +0000
    14.3 @@ -0,0 +1,157 @@
    14.4 +/*
    14.5 + * connection.c
    14.6 + *
    14.7 + * State associated with a client connection to xcs.
    14.8 + *
    14.9 + * Copyright (c) 2004, Andrew Warfield
   14.10 + */
   14.11 +
   14.12 +#include <stdio.h>
   14.13 +#include <stdlib.h>
   14.14 +#include <string.h>
   14.15 +#include "xcs.h"
   14.16 +
   14.17 +connection_t *connection_list = NULL;
   14.18 +
   14.19 +#define CONNECTED(_c) (((_c)->ctrl_fd != -1) || ((_c)->data_fd != -1))
   14.20 +
   14.21 +connection_t *get_con_by_session(unsigned long session_id)
   14.22 +{
   14.23 +    connection_t **c, *ent = NULL;
   14.24 +    
   14.25 +    c = &connection_list;
   14.26 +    
   14.27 +    DPRINTF("looking for id: %lu : %lu\n", session_id, (*c)->id);
   14.28 +    
   14.29 +    while (*c != NULL) 
   14.30 +    {
   14.31 +        if ((*c)->id == session_id) 
   14.32 +            return (*c);
   14.33 +        c = &(*c)->next;
   14.34 +    }
   14.35 +    
   14.36 +    return ent;
   14.37 +}
   14.38 +
   14.39 +connection_t *connection_new()
   14.40 +{
   14.41 +    connection_t *con;
   14.42 +    
   14.43 +    con = (connection_t *)malloc(sizeof(connection_t));
   14.44 +    if (con == NULL)
   14.45 +    {
   14.46 +        DPRINTF("couldn't allocate a new connection\n");
   14.47 +        return NULL;
   14.48 +    }
   14.49 +    
   14.50 +    con->bindings = NULL;
   14.51 +    con->data_fd = -1;
   14.52 +    con->ctrl_fd = -1;
   14.53 +    
   14.54 +    /* connections need a unique session id. 
   14.55 +     * - this approach probably gets fixed later, but for the moment
   14.56 +     * is unique, and clearly identifies a connection.
   14.57 +     */
   14.58 +    con->id = (unsigned long)con;
   14.59 +    
   14.60 +    /* add it to the connection list */
   14.61 +    con->next = connection_list;
   14.62 +    connection_list = con;
   14.63 +    
   14.64 +    return (con);
   14.65 +}
   14.66 +
   14.67 +void connection_free(connection_t *con)
   14.68 +{
   14.69 +    /* first free all subscribed bindings: */
   14.70 +    
   14.71 +    while (con->bindings != NULL)
   14.72 +        xcs_unbind(con, con->bindings->key.port, con->bindings->key.type);
   14.73 +    
   14.74 +    /* now free the connection. */
   14.75 +    free(con);
   14.76 +}
   14.77 +    
   14.78 +int connection_add_binding(connection_t *con, binding_key_t *key)
   14.79 +{
   14.80 +    binding_key_ent_t *key_ent;
   14.81 +    
   14.82 +    key_ent = (binding_key_ent_t *)malloc(sizeof(binding_key_ent_t));
   14.83 +    if (key_ent == NULL)
   14.84 +    {
   14.85 +        DPRINTF("couldn't alloc key in connection_add_binding\n");
   14.86 +        return -1;    
   14.87 +    }
   14.88 +    
   14.89 +    key_ent->key = *key;
   14.90 +    key_ent->next = con->bindings;
   14.91 +    con->bindings = key_ent;
   14.92 +    
   14.93 +    return 0;
   14.94 +}
   14.95 +
   14.96 +int connection_remove_binding(connection_t *con, binding_key_t *key)
   14.97 +{
   14.98 +    binding_key_ent_t *key_ent;
   14.99 +    binding_key_ent_t **curs = &con->bindings;
  14.100 +    
  14.101 +    while ((*curs != NULL) && (!BINDING_KEYS_EQUAL(&(*curs)->key, key)))
  14.102 +        curs = &(*curs)->next;
  14.103 +    
  14.104 +    if (*curs != NULL) {
  14.105 +        key_ent = *curs;
  14.106 +        *curs = (*curs)->next;
  14.107 +        free(key_ent);
  14.108 +    }
  14.109 +    
  14.110 +    return 0;   
  14.111 +}
  14.112 +
  14.113 +
  14.114 +int connection_has_binding(connection_t *con, binding_key_t *key)
  14.115 +{
  14.116 +    binding_key_ent_t *ent;
  14.117 +    int ret = 0;
  14.118 +    
  14.119 +    ent = con->bindings;
  14.120 +    
  14.121 +    while (ent != NULL) 
  14.122 +    {
  14.123 +        if (BINDING_KEYS_EQUAL(key, &ent->key))
  14.124 +        {
  14.125 +            ret = 1;
  14.126 +            break;
  14.127 +        }
  14.128 +        ent = ent->next;
  14.129 +    }
  14.130 +    
  14.131 +    return ret;
  14.132 +}
  14.133 +
  14.134 +
  14.135 +void gc_connection_list(void)
  14.136 +{
  14.137 +    connection_t **c, *ent = NULL;
  14.138 +    struct timeval now, delta;
  14.139 +
  14.140 +    c = &connection_list;
  14.141 +    gettimeofday(&now, NULL);
  14.142 +
  14.143 +    while ( *c != NULL )
  14.144 +    {
  14.145 +        if ( !CONNECTED(*c) )
  14.146 +        {
  14.147 +            timersub(&now, &(*c)->disconnect_time, &delta);
  14.148 +            if ( delta.tv_sec >= XCS_SESSION_TIMEOUT )
  14.149 +            {
  14.150 +                DPRINTF("        : Freeing connection %lu after %lds\n", 
  14.151 +                     (*c)->id, delta.tv_sec);
  14.152 +                ent = *c;
  14.153 +                *c = (*c)->next;
  14.154 +                connection_free(ent);
  14.155 +                continue;
  14.156 +            }
  14.157 +        }
  14.158 +        c = &(*c)->next;
  14.159 +    }
  14.160 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/xcs/ctrl_interface.c	Fri Dec 31 17:26:00 2004 +0000
    15.3 @@ -0,0 +1,269 @@
    15.4 +/* control_interface.c
    15.5 + *
    15.6 + * Interfaces to control message rings to VMs.
    15.7 + *
    15.8 + * Most of this is directly based on the original xu interface to python 
    15.9 + * written by Keir Fraser.
   15.10 + *
   15.11 + * (c) 2004, Andrew Warfield
   15.12 + *
   15.13 + */
   15.14 +
   15.15 +#include <stdio.h>
   15.16 +#include <stdlib.h>
   15.17 +#include <string.h>
   15.18 +#include <sys/ioctl.h>
   15.19 +#include <sys/mman.h>
   15.20 +#include <errno.h>
   15.21 +#include "xcs.h"
   15.22 +
   15.23 +static int xc_handle = -1;
   15.24 +
   15.25 +/* Called at start-of-day when using the control channel interface. */
   15.26 +int ctrl_chan_init(void)
   15.27 +{
   15.28 +    if ( (xc_handle = xc_interface_open()) == -1 )
   15.29 +    {
   15.30 +        DPRINTF("Could not open Xen control interface");
   15.31 +        return -1;
   15.32 +    }
   15.33 +    
   15.34 +    return 0;
   15.35 +}
   15.36 +
   15.37 +static control_if_t *map_control_interface(int fd, unsigned long pfn,
   15.38 +					   u32 dom)
   15.39 +{
   15.40 +    char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
   15.41 +					PROT_READ|PROT_WRITE, pfn );
   15.42 +    if ( vaddr == NULL )
   15.43 +        return NULL;
   15.44 +    return (control_if_t *)(vaddr + 2048);
   15.45 +}
   15.46 +
   15.47 +static void unmap_control_interface(int fd, control_if_t *c)
   15.48 +{
   15.49 +    char *vaddr = (char *)c - 2048;
   15.50 +    (void)munmap(vaddr, PAGE_SIZE);
   15.51 +}
   15.52 +
   15.53 +int ctrl_chan_notify(control_channel_t *cc)
   15.54 +{
   15.55 +    return xc_evtchn_send(xc_handle, cc->local_port);
   15.56 +}
   15.57 +
   15.58 +int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *dmsg)
   15.59 +{
   15.60 +    control_msg_t     *smsg;
   15.61 +    RING_IDX          c = cc->tx_ring.req_cons;
   15.62 +
   15.63 +    if ( !RING_HAS_UNCONSUMED_REQUESTS(CTRL_RING, &cc->tx_ring) )
   15.64 +    {
   15.65 +        DPRINTF("no request to read\n");
   15.66 +        return -1;
   15.67 +    }
   15.68 +    
   15.69 +    rmb(); /* make sure we see the data associated with the request */
   15.70 +    smsg = RING_GET_REQUEST(CTRL_RING, &cc->tx_ring, c);
   15.71 +    memcpy(&dmsg->msg, smsg, sizeof(*smsg));
   15.72 +    if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
   15.73 +        dmsg->msg.length = sizeof(dmsg->msg.msg);
   15.74 +    cc->tx_ring.req_cons++;
   15.75 +    return 0;
   15.76 +}
   15.77 +
   15.78 +int ctrl_chan_write_request(control_channel_t *cc, 
   15.79 +                            xcs_control_msg_t *smsg)
   15.80 +{
   15.81 +    control_msg_t *dmsg;
   15.82 +    RING_IDX       p = cc->rx_ring.req_prod_pvt;
   15.83 +    
   15.84 +    if ( RING_FULL(CTRL_RING, &cc->rx_ring) )
   15.85 +    {
   15.86 +        DPRINTF("no space to write request");
   15.87 +        return -ENOSPC;
   15.88 +    }
   15.89 +
   15.90 +    dmsg = RING_GET_REQUEST(CTRL_RING, &cc->rx_ring, p);
   15.91 +    memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
   15.92 +
   15.93 +    wmb();
   15.94 +    cc->rx_ring.req_prod_pvt++;
   15.95 +    RING_PUSH_REQUESTS(CTRL_RING, &cc->rx_ring);
   15.96 +    
   15.97 +    return 0;
   15.98 +}
   15.99 +
  15.100 +int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *dmsg)
  15.101 +{
  15.102 +    control_msg_t     *smsg;
  15.103 +    RING_IDX          c = cc->rx_ring.rsp_cons;
  15.104 +    
  15.105 +    if ( !RING_HAS_UNCONSUMED_RESPONSES(CTRL_RING, &cc->rx_ring) )
  15.106 +    {
  15.107 +        DPRINTF("no response to read");
  15.108 +        return -1;
  15.109 +    }
  15.110 +
  15.111 +    rmb(); /* make sure we see the data associated with the request */
  15.112 +    smsg = RING_GET_RESPONSE(CTRL_RING, &cc->rx_ring, c);
  15.113 +    memcpy(&dmsg->msg, smsg, sizeof(*smsg));
  15.114 +    if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
  15.115 +        dmsg->msg.length = sizeof(dmsg->msg.msg);
  15.116 +    cc->rx_ring.rsp_cons++;
  15.117 +    return 0;
  15.118 +}
  15.119 +
  15.120 +int ctrl_chan_write_response(control_channel_t *cc, 
  15.121 +                             xcs_control_msg_t *smsg)
  15.122 +{
  15.123 +    control_msg_t  *dmsg;
  15.124 +    RING_IDX        p = cc->tx_ring.rsp_prod_pvt;
  15.125 +
  15.126 +    /* akw: if the ring is synchronous, you should never need this test! */
  15.127 +    /* (but it was in the original code... )                             */
  15.128 +    if ( cc->tx_ring.req_cons == cc->tx_ring.rsp_prod_pvt )
  15.129 +    {
  15.130 +        DPRINTF("no space to write response");
  15.131 +        return -ENOSPC;
  15.132 +    }
  15.133 +
  15.134 +    dmsg = RING_GET_RESPONSE(CTRL_RING, &cc->tx_ring, p);
  15.135 +    memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
  15.136 +
  15.137 +    wmb();
  15.138 +    cc->tx_ring.rsp_prod_pvt++;
  15.139 +    RING_PUSH_RESPONSES(CTRL_RING, &cc->tx_ring);
  15.140 +    
  15.141 +    return 0;
  15.142 +}
  15.143 +
  15.144 +int ctrl_chan_request_to_read(control_channel_t *cc)
  15.145 +{
  15.146 +    return (RING_HAS_UNCONSUMED_REQUESTS(CTRL_RING, &cc->tx_ring));
  15.147 +}
  15.148 +
  15.149 +int ctrl_chan_space_to_write_request(control_channel_t *cc)
  15.150 +{
  15.151 +    return (!(RING_FULL(CTRL_RING, &cc->rx_ring)));
  15.152 +}
  15.153 +
  15.154 +int ctrl_chan_response_to_read(control_channel_t *cc)
  15.155 +{
  15.156 +    return (RING_HAS_UNCONSUMED_RESPONSES(CTRL_RING, &cc->rx_ring));
  15.157 +}
  15.158 +
  15.159 +int ctrl_chan_space_to_write_response(control_channel_t *cc)
  15.160 +{
  15.161 +    /* again, there is something fishy here. */
  15.162 +    return ( cc->tx_ring.req_cons != cc->tx_ring.rsp_prod_pvt );
  15.163 +}
  15.164 +
  15.165 +int ctrl_chan_connect(control_channel_t *cc)
  15.166 +{
  15.167 +    xc_dominfo_t info;
  15.168 +
  15.169 +    if ( cc->connected )
  15.170 +    {
  15.171 +	return 0;
  15.172 +    }
  15.173 +
  15.174 +    if ( (xc_domain_getinfo(xc_handle, cc->remote_dom, 1, &info) != 1) ||
  15.175 +         (info.domid != cc->remote_dom) )
  15.176 +    {
  15.177 +        DPRINTF("Failed to obtain domain status");
  15.178 +        return -1;
  15.179 +    }
  15.180 +
  15.181 +    cc->interface = 
  15.182 +        map_control_interface(xc_handle, info.shared_info_frame,
  15.183 +			      cc->remote_dom);
  15.184 +
  15.185 +    if ( cc->interface == NULL )
  15.186 +    {
  15.187 +        DPRINTF("Failed to map domain control interface");
  15.188 +        return -1;
  15.189 +    }
  15.190 +
  15.191 +    /* Synchronise ring indexes. */
  15.192 +    BACK_RING_ATTACH(CTRL_RING, &cc->tx_ring, &cc->interface->tx_ring);
  15.193 +    FRONT_RING_ATTACH(CTRL_RING, &cc->rx_ring, &cc->interface->rx_ring);
  15.194 +
  15.195 +    cc->connected = 1;
  15.196 +
  15.197 +    return 0;
  15.198 +}
  15.199 +
  15.200 +void ctrl_chan_disconnect(control_channel_t *cc)
  15.201 +{
  15.202 +    if ( cc->connected )
  15.203 +	unmap_control_interface(xc_handle, cc->interface);
  15.204 +    cc->connected = 0;
  15.205 +}
  15.206 +
  15.207 +
  15.208 +control_channel_t *ctrl_chan_new(u32 dom, int local_port, int remote_port)
  15.209 +{
  15.210 +    control_channel_t *cc;
  15.211 +   
  15.212 +    cc = (control_channel_t *)malloc(sizeof(control_channel_t));
  15.213 +    if ( cc == NULL ) return NULL;
  15.214 +    
  15.215 +    cc->connected  = 0;
  15.216 +    cc->remote_dom = dom;
  15.217 +
  15.218 +    if ( dom == 0 )
  15.219 +    {
  15.220 +        /*
  15.221 +         * The control-interface event channel for DOM0 is already set up.
  15.222 +         * We use an ioctl to discover the port at our end of the channel.
  15.223 +         */
  15.224 +        local_port  = ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, 
  15.225 +                            NULL);
  15.226 +        remote_port = -1; /* We don't need the remote end of the DOM0 link. */
  15.227 +        if ( local_port < 0 )
  15.228 +        {
  15.229 +            DPRINTF("Could not open channel to DOM0");
  15.230 +            goto fail;
  15.231 +        }
  15.232 +    }
  15.233 +    else if ( xc_evtchn_bind_interdomain(xc_handle, 
  15.234 +                                         DOMID_SELF, dom, 
  15.235 +                                         &local_port, &remote_port) != 0 )
  15.236 +    {
  15.237 +        DPRINTF("Could not open channel to domain");
  15.238 +        goto fail;
  15.239 +    }
  15.240 +
  15.241 +    cc->local_port  = local_port;
  15.242 +    cc->remote_port = remote_port;
  15.243 +
  15.244 +    if ( ctrl_chan_connect(cc) != 0 )
  15.245 +        goto fail;
  15.246 +
  15.247 +    return cc;
  15.248 +    
  15.249 + fail:
  15.250 +    if ( dom != 0 )
  15.251 +        (void)xc_evtchn_close(xc_handle, DOMID_SELF, local_port);
  15.252 + 
  15.253 +    free(cc);
  15.254 +    
  15.255 +    return NULL;        
  15.256 +}
  15.257 +
  15.258 +void ctrl_chan_free(control_channel_t *cc)
  15.259 +{
  15.260 +    ctrl_chan_disconnect(cc);
  15.261 +    if ( cc->remote_dom != 0 )
  15.262 +        (void)xc_evtchn_close(xc_handle, DOMID_SELF, cc->local_port);
  15.263 +    free(cc);
  15.264 +}
  15.265 +
  15.266 +
  15.267 +/* other libxc commands: */
  15.268 +
  15.269 +int ctrl_chan_bind_virq(int virq, int *port)
  15.270 +{
  15.271 +    return xc_evtchn_bind_virq(xc_handle, virq, port);
  15.272 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/xcs/evtchn.c	Fri Dec 31 17:26:00 2004 +0000
    16.3 @@ -0,0 +1,108 @@
    16.4 +/* evtchn.c
    16.5 + *
    16.6 + * Interfaces to event channel driver.
    16.7 + *
    16.8 + * Most of this is directly based on the original xu interface to python 
    16.9 + * written by Keir Fraser.
   16.10 + *
   16.11 + * (c) 2004, Andrew Warfield
   16.12 + *
   16.13 + */
   16.14 + 
   16.15 +#include <stdio.h>
   16.16 +#include <stdlib.h>
   16.17 +#include <sys/ioctl.h>
   16.18 +#include <sys/stat.h>
   16.19 +#include <sys/sysmacros.h> /* XOPEN drops makedev, this gets it back. */
   16.20 +#include <fcntl.h>
   16.21 +#include <unistd.h>
   16.22 +#include <errno.h>
   16.23 +#include "xcs.h"
   16.24 +
   16.25 +static int evtchn_fd = -1;
   16.26 +
   16.27 +/* NB. The following should be kept in sync with the kernel's evtchn driver. */
   16.28 +#define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
   16.29 +#define EVTCHN_DEV_MAJOR 10
   16.30 +#define EVTCHN_DEV_MINOR 201
   16.31 +/* /dev/xen/evtchn ioctls: */
   16.32 +/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
   16.33 +#define EVTCHN_RESET  _IO('E', 1)
   16.34 +/* EVTCHN_BIND: Bind to teh specified event-channel port. */
   16.35 +#define EVTCHN_BIND   _IO('E', 2)
   16.36 +/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
   16.37 +#define EVTCHN_UNBIND _IO('E', 3)
   16.38 +
   16.39 +int evtchn_read()
   16.40 +{
   16.41 +    u16 v;
   16.42 +    int bytes;
   16.43 +
   16.44 +    while ( (bytes = read(evtchn_fd, &v, sizeof(v))) == -1 )
   16.45 +    {
   16.46 +        if ( errno == EINTR )
   16.47 +            continue;
   16.48 +        /* EAGAIN was cased to return 'None' in the python version... */
   16.49 +        return -errno;
   16.50 +    }
   16.51 +    
   16.52 +    if ( bytes == sizeof(v) )
   16.53 +        return v;
   16.54 +    
   16.55 +    /* bad return */
   16.56 +    return -1;
   16.57 +}
   16.58 +
   16.59 +void evtchn_unmask(u16 idx)
   16.60 +{
   16.61 +    (void)write(evtchn_fd, &idx, sizeof(idx));
   16.62 +}
   16.63 +
   16.64 +int evtchn_bind(int idx)
   16.65 +{
   16.66 +    if ( ioctl(evtchn_fd, EVTCHN_BIND, idx) != 0 )
   16.67 +        return -errno;
   16.68 +    
   16.69 +    return 0;
   16.70 +}
   16.71 +
   16.72 +int evtchn_unbind(int idx)
   16.73 +{
   16.74 +    if ( ioctl(evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
   16.75 +        return -errno;
   16.76 +
   16.77 +    return 0;
   16.78 +}
   16.79 +
   16.80 +int evtchn_open(void)
   16.81 +{
   16.82 +    struct stat st;
   16.83 +    
   16.84 +    /* Make sure any existing device file links to correct device. */
   16.85 +    if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
   16.86 +         !S_ISCHR(st.st_mode) ||
   16.87 +         (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
   16.88 +        (void)unlink(EVTCHN_DEV_NAME);
   16.89 +
   16.90 + reopen:
   16.91 +    evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR); 
   16.92 +    if ( evtchn_fd == -1 )
   16.93 +    {
   16.94 +        if ( (errno == ENOENT) &&
   16.95 +             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
   16.96 +             (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, 
   16.97 +                    makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
   16.98 +            goto reopen;
   16.99 +        return -errno;
  16.100 +    }
  16.101 +    /*set_cloexec(evtchn_fd); -- no longer required*/
  16.102 +printf("Eventchan_fd is %d\n", evtchn_fd);
  16.103 +    return evtchn_fd;
  16.104 +}
  16.105 +
  16.106 +void evtchn_close()
  16.107 +{
  16.108 +    (void)close(evtchn_fd);
  16.109 +    evtchn_fd = -1;
  16.110 +}
  16.111 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/xcs/xcs.c	Fri Dec 31 17:26:00 2004 +0000
    17.3 @@ -0,0 +1,833 @@
    17.4 +/* xcs.c 
    17.5 + *
    17.6 + * xcs - Xen Control Switch
    17.7 + *
    17.8 + * Copyright (c) 2004, Andrew Warfield
    17.9 + */
   17.10 + 
   17.11 +/*
   17.12 +
   17.13 +  Things we need to select on in xcs:
   17.14 +  
   17.15 +  1. Events arriving on /dev/evtchn
   17.16 +  
   17.17 +    These will kick a function to read everything off the fd, and scan the
   17.18 +    associated control message rings, resulting in notifications sent on
   17.19 +    data channels to connected clients.
   17.20 +    
   17.21 +  2. New TCP connections on XCS_PORT.
   17.22 +  
   17.23 +    These will either be control (intially) or associated data connections.
   17.24 +    
   17.25 +    Control connections will instantiate or rebind to an existing connnection
   17.26 +    struct.  The control channel is used to configure what events will be 
   17.27 +    received on an associated data channel.  These two channels are split
   17.28 +    out because the control channel is synchronous, all messages will return
   17.29 +    a result from XCS.  The data channel is effectively asynchronous, events
   17.30 +    may arrive in the middle of a control message exchange.  Additionally, 
   17.31 +    Having two TCP connections allows the client side to have a blocking
   17.32 +    listen loop for data messages, while independently interacting on the 
   17.33 +    control channel at other places in the code.
   17.34 +    
   17.35 +    Data connections attach to an existing control struct, using a session
   17.36 +    id that is passed during the control connect.  There is currently a 
   17.37 +    one-to-one relationship between data and control channels, but there
   17.38 +    could just as easily be many data channels, if there were a set of 
   17.39 +    clients with identical interests, or if you wanted to trace an existing
   17.40 +    client's data traffic.
   17.41 +    
   17.42 + 3. Messages arriving on open TCP connections.
   17.43 +    There are three types of open connections:
   17.44 +     
   17.45 +    3a. Messages arriving on open control channel file descriptors.
   17.46 + 
   17.47 +        [description of the control protocol here]
   17.48 + 
   17.49 +    3b. Messages arriving on open data channel file descriptors.
   17.50 + 
   17.51 +        [description of the data protocol here]
   17.52 +        
   17.53 +    3c. Messages arriving on (new) unbound connections.
   17.54 +    
   17.55 +        A connection must issue a XCS_CONNECT message to specify what
   17.56 +        it is, after which the connection is moved into one of the above 
   17.57 +        two groups.
   17.58 + 
   17.59 + Additionally, we need a periodic timer to do housekeeping.
   17.60 + 
   17.61 + 4. Every XCS_GC_INTERVAL seconds, we need to clean up outstanding state. 
   17.62 +    Specifically, we garbage collect any sessions (connection_t structs)
   17.63 +    that have been unconnected for a period of time (XCS_SESSION_TIMEOUT), 
   17.64 +    and close any connections that have been openned, but not connected
   17.65 +    as a control or data connection (XCS_UFD_TIMEOUT).
   17.66 +
   17.67 +*/
   17.68 +
   17.69 +#include <stdlib.h>
   17.70 +#include <stdio.h>
   17.71 +#include <unistd.h>
   17.72 +#include <sys/time.h>
   17.73 +#include <sys/types.h>
   17.74 +#include <string.h>
   17.75 +#include <signal.h>
   17.76 +#include <sys/socket.h>
   17.77 +#include <netinet/in.h>
   17.78 +#include <arpa/inet.h>
   17.79 +#include <errno.h>
   17.80 +#include "xcs.h"
   17.81 +
   17.82 +#undef fd_max
   17.83 +#define fd_max(x,y) ((x) > (y) ? (x) : (y))
   17.84 +
   17.85 +/* ------[ Control channel interfaces ]------------------------------------*/
   17.86 +
   17.87 +static control_channel_t *cc_list[NR_EVENT_CHANNELS];
   17.88 +static int dom_to_port[MAX_DOMS]; /* This should not be a fixed-size array.*/
   17.89 +
   17.90 +static void init_interfaces(void)
   17.91 +{
   17.92 +    int i;
   17.93 +    
   17.94 +    for (i = 0; i < MAX_DOMS; i++)
   17.95 +        dom_to_port[i] = -1;
   17.96 +    memset(cc_list, 0, sizeof cc_list);
   17.97 +}
   17.98 +
   17.99 +static control_channel_t *add_interface(u32 dom, int local_port, 
  17.100 +                                        int remote_port)
  17.101 +{
  17.102 +    control_channel_t *cc, *oldcc;
  17.103 +    int ret;
  17.104 +    
  17.105 +    if (cc_list[dom_to_port[dom]] != NULL)
  17.106 +    {
  17.107 +        return(cc_list[dom_to_port[dom]]);
  17.108 +    }
  17.109 +    
  17.110 +    if (cc_list[local_port] == NULL) 
  17.111 +    {
  17.112 +        cc = ctrl_chan_new(dom, local_port, remote_port);
  17.113 +    }
  17.114 +    
  17.115 +    if (cc == NULL)
  17.116 +        return NULL;
  17.117 +    
  17.118 +    DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
  17.119 +            dom, local_port, remote_port, cc);
  17.120 +    DPRINTF("added a new interface: dom: %u (l:%d,r:%d): %p\n",
  17.121 +            dom, cc->local_port, cc->remote_port, cc);
  17.122 +    
  17.123 +    if ((ret = evtchn_bind(cc->local_port)) != 0)
  17.124 +    {
  17.125 +        DPRINTF("Got control interface, but couldn't bind evtchan!(%d)\n", ret);
  17.126 +        ctrl_chan_free(cc);
  17.127 +        return NULL;
  17.128 +    }
  17.129 +    
  17.130 +    if ( cc_list[cc->local_port] != NULL )
  17.131 +    {
  17.132 +        oldcc = cc_list[cc->local_port];
  17.133 +        
  17.134 +        if ((oldcc->remote_dom != cc->remote_dom) ||
  17.135 +            (oldcc->remote_port != cc->remote_port))
  17.136 +        {
  17.137 +            DPRINTF("CC conflict! (port: %d, old dom: %u, new dom: %u)\n",
  17.138 +                    cc->local_port, oldcc->remote_dom, cc->remote_dom);
  17.139 +            dom_to_port[oldcc->remote_dom] = -1;
  17.140 +            ctrl_chan_free(cc_list[cc->local_port]);
  17.141 +        }
  17.142 +    }
  17.143 +     
  17.144 +    cc_list[cc->local_port] = cc;
  17.145 +    dom_to_port[cc->remote_dom] = cc->local_port;
  17.146 +    cc->type = CC_TYPE_INTERDOMAIN;
  17.147 +    cc->ref_count = 0;
  17.148 +    return cc;
  17.149 +}
  17.150 +
  17.151 +control_channel_t *add_virq(int virq)
  17.152 +{
  17.153 +    control_channel_t *cc;
  17.154 +    int virq_port;
  17.155 +    
  17.156 +    if (ctrl_chan_bind_virq(virq, &virq_port) == -1)
  17.157 +        return NULL;
  17.158 +    
  17.159 +    if ((cc_list[virq_port]       != NULL) && 
  17.160 +        (cc_list[virq_port]->type != CC_TYPE_VIRQ))
  17.161 +        return NULL; 
  17.162 +    
  17.163 +    if ((cc_list[virq_port]       != NULL) && 
  17.164 +        (cc_list[virq_port]->type == CC_TYPE_VIRQ))
  17.165 +        return cc_list[virq_port]; 
  17.166 +    
  17.167 +    cc = (control_channel_t *)malloc(sizeof(control_channel_t));
  17.168 +    if ( cc == NULL ) return NULL;
  17.169 +
  17.170 +    cc->type       = CC_TYPE_VIRQ;
  17.171 +    cc->local_port = virq_port;
  17.172 +    cc->virq       = virq;
  17.173 +    
  17.174 +    return cc;
  17.175 +}
  17.176 +
  17.177 +void get_interface(control_channel_t *cc)
  17.178 +{
  17.179 +    if (cc != NULL)
  17.180 +        cc->ref_count++;
  17.181 +}
  17.182 +    
  17.183 +void put_interface(control_channel_t *cc)
  17.184 +{
  17.185 +    if (cc != NULL)
  17.186 +    {
  17.187 +        cc->ref_count--;
  17.188 +        if (cc->ref_count <= 0)
  17.189 +        {
  17.190 +            DPRINTF("Freeing cc on port %d.\n", cc->local_port);
  17.191 +            (void)evtchn_unbind(cc->local_port);
  17.192 +            ctrl_chan_free(cc);
  17.193 +        }
  17.194 +    }
  17.195 +}
  17.196 +
  17.197 +/* ------[ Simple helpers ]------------------------------------------------*/
  17.198 +
  17.199 +/* listen_socket() is straight from paul sheer's useful select_tut manpage. */
  17.200 +static int listen_socket (int listen_port) 
  17.201 +{
  17.202 +    struct sockaddr_in a;
  17.203 +    int s;
  17.204 +    int yes;
  17.205 +
  17.206 +    if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) 
  17.207 +    {
  17.208 +        perror ("socket");
  17.209 +        return -1;
  17.210 +    }
  17.211 +    
  17.212 +    yes = 1;
  17.213 +    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  17.214 +        (char *) &yes, sizeof (yes)) < 0) 
  17.215 +    {
  17.216 +        perror ("setsockopt");
  17.217 +        close (s);
  17.218 +        return -1;
  17.219 +    }
  17.220 +
  17.221 +    memset (&a, 0, sizeof (a));
  17.222 +    a.sin_port = htons (listen_port);
  17.223 +    a.sin_family = AF_INET;
  17.224 +    if (bind(s, (struct sockaddr *) &a, sizeof (a)) < 0) 
  17.225 +    {
  17.226 +        perror ("bind");
  17.227 +        close (s);
  17.228 +        return -1;
  17.229 +    }
  17.230 +    printf ("accepting connections on port %d\n", (int) listen_port);
  17.231 +    listen (s, 10);
  17.232 +    return s;
  17.233 +}
  17.234 +
  17.235 +/* ------[ Message handlers ]----------------------------------------------*/
  17.236 +
  17.237 +#define NO_CHANGE     0
  17.238 +#define CONNECTED     1
  17.239 +#define DISCONNECTED  2
  17.240 +int handle_connect_msg( xcs_msg_t *msg, int fd )
  17.241 +{
  17.242 +    xcs_connect_msg_t *cmsg = &msg->u.connect;
  17.243 +    connection_t *con;
  17.244 +    int ret = NO_CHANGE;
  17.245 +    
  17.246 +    switch (msg->type)
  17.247 +    {
  17.248 +        case XCS_CONNECT_CTRL:
  17.249 +        {
  17.250 +            if ( cmsg->session_id == 0 )
  17.251 +            {
  17.252 +                con = connection_new();
  17.253 +                if ( con == NULL)
  17.254 +                {
  17.255 +                    msg->result = XCS_RSLT_FAILED;
  17.256 +                    break;
  17.257 +                }
  17.258 +                msg->result      = XCS_RSLT_OK;
  17.259 +                cmsg->session_id = con->id;
  17.260 +                con->ctrl_fd     = fd;
  17.261 +                ret = CONNECTED;
  17.262 +                DPRINTF("New control connection\n");
  17.263 +                break;
  17.264 +            }
  17.265 +
  17.266 +            con = get_con_by_session(cmsg->session_id);
  17.267 +            if ( con == NULL )
  17.268 +            {
  17.269 +                msg->result = XCS_RSLT_BADSESSION;
  17.270 +                break;
  17.271 +            }
  17.272 +            if ( con->ctrl_fd != -1 )
  17.273 +            {
  17.274 +                msg->result = XCS_RSLT_CONINUSE;
  17.275 +                break;
  17.276 +            }
  17.277 +            con->ctrl_fd   = fd;
  17.278 +            msg->result   = XCS_RSLT_OK;
  17.279 +            ret = CONNECTED;
  17.280 +            DPRINTF("Rebound to control connection\n");
  17.281 +            break;
  17.282 +        }
  17.283 +        case XCS_CONNECT_DATA:
  17.284 +        {
  17.285 +            con = get_con_by_session(cmsg->session_id);
  17.286 +            if ( con == NULL )
  17.287 +            {
  17.288 +                msg->result = XCS_RSLT_BADSESSION;
  17.289 +                break;
  17.290 +            }
  17.291 +            if ( con->data_fd != -1 )
  17.292 +            {
  17.293 +                msg->result = XCS_RSLT_CONINUSE;
  17.294 +                break;
  17.295 +            }
  17.296 +            con->data_fd   = fd;
  17.297 +            msg->result   = XCS_RSLT_OK;
  17.298 +            ret = CONNECTED;
  17.299 +            DPRINTF("Attached data connection\n");
  17.300 +            break;
  17.301 +
  17.302 +        }
  17.303 +        case XCS_CONNECT_BYE:
  17.304 +        {
  17.305 +            close ( fd );
  17.306 +            ret = DISCONNECTED;
  17.307 +            break;
  17.308 +        }
  17.309 +    }   
  17.310 +    
  17.311 +    return ret;
  17.312 +}
  17.313 +
  17.314 +int handle_control_message( connection_t *con, xcs_msg_t *msg )
  17.315 +{
  17.316 +    int ret;
  17.317 +    int reply_needed = 1;
  17.318 +            
  17.319 +    DPRINTF("Got message, type %u.\n", msg->type);
  17.320 +
  17.321 +    switch (msg->type)
  17.322 +    {
  17.323 +        case XCS_MSG_BIND:
  17.324 +        {
  17.325 +            xcs_bind_msg_t *bmsg = &msg->u.bind;
  17.326 +
  17.327 +            if ( ! BIND_MSG_VALID(bmsg) )
  17.328 +            {
  17.329 +                msg->result = XCS_RSLT_BADREQUEST;
  17.330 +                break;
  17.331 +            }
  17.332 +            
  17.333 +            ret = xcs_bind(con, bmsg->port, bmsg->type);
  17.334 +            if (ret == 0) {
  17.335 +                msg->result = XCS_RSLT_OK;
  17.336 +            } else {
  17.337 +                msg->result = XCS_RSLT_FAILED;
  17.338 +            }
  17.339 +            break;
  17.340 +        }
  17.341 +        case XCS_MSG_UNBIND:
  17.342 +        {
  17.343 +            xcs_bind_msg_t *bmsg = &msg->u.bind;
  17.344 +
  17.345 +            if ( ! BIND_MSG_VALID(bmsg) )
  17.346 +            {
  17.347 +                msg->result = XCS_RSLT_BADREQUEST;
  17.348 +                break;
  17.349 +            }
  17.350 +            
  17.351 +            ret = xcs_unbind(con, bmsg->port, bmsg->type);
  17.352 +            if (ret == 0) {
  17.353 +                msg->result = XCS_RSLT_OK;
  17.354 +            } else {
  17.355 +                msg->result = XCS_RSLT_FAILED;
  17.356 +            }
  17.357 +            break;
  17.358 +        }    
  17.359 +        case XCS_VIRQ_BIND:
  17.360 +        {
  17.361 +            control_channel_t *cc;
  17.362 +            xcs_virq_msg_t *vmsg = &msg->u.virq;
  17.363 +            if ( ! VIRQ_MSG_VALID(vmsg) )
  17.364 +            {
  17.365 +                msg->result = XCS_RSLT_BADREQUEST;
  17.366 +                break;
  17.367 +            }
  17.368 +
  17.369 +            cc = add_virq(vmsg->virq);
  17.370 +            if (cc == NULL)
  17.371 +            {
  17.372 +                msg->result = XCS_RSLT_FAILED;
  17.373 +                break;
  17.374 +            }
  17.375 +            ret = xcs_bind(con, cc->local_port, TYPE_VIRQ);
  17.376 +            if (ret == 0) {
  17.377 +                vmsg->port   = cc->local_port;
  17.378 +                msg->result  = XCS_RSLT_OK;
  17.379 +            } else {
  17.380 +                msg->result = XCS_RSLT_FAILED;
  17.381 +            }
  17.382 +            break;
  17.383 +        }
  17.384 +
  17.385 +        case XCS_CIF_NEW_CC:
  17.386 +        {
  17.387 +            control_channel_t *cc;
  17.388 +            xcs_interface_msg_t *imsg = &msg->u.interface;
  17.389 +
  17.390 +            if ( ! INTERFACE_MSG_VALID(imsg) )
  17.391 +            {
  17.392 +                msg->result = XCS_RSLT_BADREQUEST;
  17.393 +                break;
  17.394 +            }
  17.395 +
  17.396 +            cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
  17.397 +            if (cc != NULL) {
  17.398 +                get_interface(cc);
  17.399 +                msg->result       = XCS_RSLT_OK;
  17.400 +                imsg->local_port  = cc->local_port;
  17.401 +                imsg->remote_port = cc->remote_port;
  17.402 +            } else {
  17.403 +                msg->result = XCS_RSLT_FAILED;
  17.404 +            }
  17.405 +            break;
  17.406 +        }
  17.407 +
  17.408 +        case XCS_CIF_FREE_CC:
  17.409 +        {
  17.410 +            control_channel_t *cc;
  17.411 +            xcs_interface_msg_t *imsg = &msg->u.interface;
  17.412 +
  17.413 +            if ( ! INTERFACE_MSG_VALID(imsg) )
  17.414 +            {
  17.415 +                msg->result = XCS_RSLT_BADREQUEST;
  17.416 +                break;
  17.417 +            }
  17.418 +
  17.419 +            cc = add_interface(imsg->dom, imsg->local_port, imsg->remote_port);
  17.420 +            if (cc != NULL) {
  17.421 +                put_interface(cc);
  17.422 +            } 
  17.423 +            msg->result       = XCS_RSLT_OK;
  17.424 +            break;
  17.425 +        }
  17.426 +    }
  17.427 +    return reply_needed;
  17.428 +}
  17.429 +
  17.430 +void handle_data_message( connection_t *con, xcs_msg_t *msg )
  17.431 +{
  17.432 +    control_channel_t *cc;
  17.433 +    xcs_control_msg_t *cmsg = &msg->u.control;
  17.434 +    int port;
  17.435 +    
  17.436 +    switch (msg->type)
  17.437 +    {
  17.438 +    case XCS_REQUEST:
  17.439 +        if ( cmsg->remote_dom > MAX_DOMS )
  17.440 +            break;
  17.441 +        
  17.442 +        port = dom_to_port[cmsg->remote_dom];
  17.443 +        if (port == -1) break;
  17.444 +        cc = cc_list[port];
  17.445 +        if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
  17.446 +        {
  17.447 +            DPRINTF("DN:REQ: dom:%d port: %d type: %d\n", 
  17.448 +                    cc->remote_dom, cc->local_port, 
  17.449 +                    cmsg->msg.type);
  17.450 +            ctrl_chan_write_request(cc, cmsg);
  17.451 +            ctrl_chan_notify(cc);
  17.452 +        } else {
  17.453 +            DPRINTF("tried to send a REQ to a null cc\n.");
  17.454 +        }
  17.455 +        break;
  17.456 +
  17.457 +    case XCS_RESPONSE:
  17.458 +        if ( cmsg->remote_dom > MAX_DOMS )
  17.459 +            break;
  17.460 +        
  17.461 +        port = dom_to_port[cmsg->remote_dom];
  17.462 +        if (port == -1) break;
  17.463 +        cc = cc_list[port];
  17.464 +        if ((cc != NULL) && ( cc->type == CC_TYPE_INTERDOMAIN ))
  17.465 +        {
  17.466 +            DPRINTF("DN:RSP: dom:%d port: %d type: %d\n", 
  17.467 +                    cc->remote_dom, cc->local_port, 
  17.468 +                    cmsg->msg.type);
  17.469 +            ctrl_chan_write_response(cc, cmsg);
  17.470 +            ctrl_chan_notify(cc);
  17.471 +        }
  17.472 +        break;
  17.473 +
  17.474 +    case XCS_VIRQ:
  17.475 +        if ( !(PORT_VALID(cmsg->local_port)) )
  17.476 +            break;
  17.477 +            
  17.478 +        cc = cc_list[cmsg->local_port];
  17.479 +        
  17.480 +        if ((cc != NULL) && ( cc->type == CC_TYPE_VIRQ ))
  17.481 +        {
  17.482 +            DPRINTF("DN:VIRQ:  virq: %d port: %d\n", 
  17.483 +                    cc->virq, cc->local_port);
  17.484 +            ctrl_chan_notify(cc);
  17.485 +        }
  17.486 +        break;
  17.487 +    }
  17.488 +}
  17.489 +    
  17.490 +/* ------[ Control interface handler ]-------------------------------------*/
  17.491 +
  17.492 +/* passed as a function pointer to the lookup. */
  17.493 +void send_kmsg(connection_t *c, void *arg)
  17.494 +{
  17.495 +    xcs_msg_t *msg = (xcs_msg_t *)arg;
  17.496 +
  17.497 +    DPRINTF("       -> CONNECTION %d\n", c->data_fd);
  17.498 +    if (c->data_fd > 0)
  17.499 +    {
  17.500 +      send(c->data_fd, msg, sizeof(xcs_msg_t), 0);
  17.501 +    }
  17.502 +}
  17.503 +
  17.504 +int handle_ctrl_if(void)
  17.505 +{
  17.506 +    control_channel_t *cc;
  17.507 +    control_msg_t     *msg;
  17.508 +    xcs_msg_t          kmsg;
  17.509 +    int                chan, ret;
  17.510 +    
  17.511 +    DPRINTF("Event thread kicked!\n");
  17.512 +again:
  17.513 +    while ((chan = evtchn_read()) > 0)
  17.514 +    {
  17.515 +        evtchn_unmask(chan);
  17.516 +        cc = cc_list[chan];
  17.517 +        if (cc_list[chan] == NULL) {
  17.518 +            DPRINTF("event from unknown channel (%d)\n", chan);
  17.519 +            continue;
  17.520 +        }
  17.521 +
  17.522 +        if ( cc_list[chan]->type == CC_TYPE_VIRQ )
  17.523 +        {
  17.524 +            DPRINTF("UP:VIRQ: virq:%d port: %d\n",
  17.525 +                    cc->virq, cc->local_port);
  17.526 +            kmsg.type = XCS_VIRQ;
  17.527 +            kmsg.u.control.local_port = cc->local_port;
  17.528 +            xcs_lookup(cc->local_port, TYPE_VIRQ, send_kmsg, &kmsg);
  17.529 +            continue;
  17.530 +        }
  17.531 +
  17.532 +        while (ctrl_chan_request_to_read(cc))
  17.533 +        {
  17.534 +            msg = &kmsg.u.control.msg;
  17.535 +            kmsg.type = XCS_REQUEST;
  17.536 +            kmsg.u.control.remote_dom = cc->remote_dom;
  17.537 +            kmsg.u.control.local_port = cc->local_port;
  17.538 +            ret = ctrl_chan_read_request(cc, &kmsg.u.control);
  17.539 +            DPRINTF("UP:REQ: dom:%d port: %d type: %d len: %d\n", 
  17.540 +                    cc->remote_dom, cc->local_port, 
  17.541 +                    msg->type, msg->length);
  17.542 +            if (ret == 0)
  17.543 +                xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
  17.544 +        }
  17.545 +
  17.546 +        while (ctrl_chan_response_to_read(cc))
  17.547 +        {
  17.548 +            msg = &kmsg.u.control.msg;
  17.549 +            kmsg.type = XCS_RESPONSE;
  17.550 +            kmsg.u.control.remote_dom = cc->remote_dom;
  17.551 +            kmsg.u.control.local_port = cc->local_port;
  17.552 +            ret = ctrl_chan_read_response(cc, &kmsg.u.control);
  17.553 +            DPRINTF("UP:RSP: dom:%d port: %d type: %d len: %d\n", 
  17.554 +                    cc->remote_dom, cc->local_port, 
  17.555 +                    msg->type, msg->length);
  17.556 +            if (ret == 0)
  17.557 +                xcs_lookup(cc->local_port, msg->type, send_kmsg, &kmsg);
  17.558 +        }
  17.559 +    }
  17.560 +    
  17.561 +    if (chan == -EINTR)
  17.562 +        goto again;
  17.563 +    
  17.564 +    return chan;
  17.565 +}
  17.566 +
  17.567 +  
  17.568 +/* ------[ Main xcs code / big select loop ]-------------------------------*/
  17.569 +
  17.570 +                
  17.571 +typedef struct unbound_fd_st {
  17.572 +    int                   fd;
  17.573 +    struct timeval        born;
  17.574 +    struct unbound_fd_st *next;
  17.575 +} unbound_fd_t;
  17.576 +
  17.577 +/* This makes ufd point to the next entry in the list, so need to   *
  17.578 + * break/continue if called while iterating.                        */
  17.579 +void delete_ufd(unbound_fd_t **ufd)
  17.580 +{
  17.581 +    unbound_fd_t *del_ufd;
  17.582 +    
  17.583 +    del_ufd = *ufd;
  17.584 +    *ufd    = (*ufd)->next;
  17.585 +    free( del_ufd );
  17.586 +}
  17.587 +
  17.588 +void gc_ufd_list( unbound_fd_t **ufd )
  17.589 +{
  17.590 +    struct timeval now, delta;
  17.591 +    
  17.592 +    gettimeofday(&now, NULL);
  17.593 +    
  17.594 +    while ( *ufd != NULL )
  17.595 +    {
  17.596 +        timersub(&now, &(*ufd)->born, &delta);
  17.597 +        if (delta.tv_sec > XCS_UFD_TIMEOUT)
  17.598 +        {
  17.599 +            DPRINTF("GC-UFD: closing fd: %d\n", (*ufd)->fd);
  17.600 +            close((*ufd)->fd);
  17.601 +            delete_ufd(ufd);
  17.602 +            continue;
  17.603 +        }
  17.604 +        ufd = &(*ufd)->next;
  17.605 +    }
  17.606 +}
  17.607 +
  17.608 +int main (int argc, char*argv[])
  17.609 +{
  17.610 +    int listen_fd, evtchn_fd;
  17.611 +    unbound_fd_t *unbound_fd_list = NULL, **ufd;
  17.612 +    struct timeval timeout = { XCS_GC_INTERVAL, 0 };
  17.613 +    connection_t **con;
  17.614 +    
  17.615 +    /* Initialize xc and event connections. */
  17.616 +    if (ctrl_chan_init() != 0)
  17.617 +    {
  17.618 +        printf("Couldn't open conneciton to libxc.\n");
  17.619 +        exit(-1);
  17.620 +    }
  17.621 +    
  17.622 +    if ((evtchn_fd = evtchn_open()) < 0)
  17.623 +    {
  17.624 +        printf("Couldn't open event channel driver interface.\n");
  17.625 +        exit(-1);
  17.626 +    }
  17.627 +   
  17.628 +    /* Initialize control interfaces, bindings. */
  17.629 +    init_interfaces();
  17.630 +    init_bindings();
  17.631 +    
  17.632 +    listen_fd = listen_socket(XCS_TCP_PORT);
  17.633 +    
  17.634 +    for (;;)
  17.635 +    {
  17.636 +        int n, ret;
  17.637 +        fd_set rd, wr, er;
  17.638 +        FD_ZERO ( &rd );
  17.639 +        FD_ZERO ( &wr );
  17.640 +        FD_ZERO ( &er );
  17.641 +        
  17.642 +        /* TCP listen fd: */
  17.643 +        FD_SET ( listen_fd, &rd );
  17.644 +        n = fd_max ( n, listen_fd );
  17.645 +        
  17.646 +        /* Evtchn fd: */
  17.647 +        FD_SET ( evtchn_fd, &rd );
  17.648 +        n = fd_max ( n, evtchn_fd );
  17.649 +        
  17.650 +        /* unbound connection fds: */
  17.651 +        ufd = &unbound_fd_list;
  17.652 +        while ((*ufd) != NULL) 
  17.653 +        {
  17.654 +            FD_SET ( (*ufd)->fd, &rd );
  17.655 +            n = fd_max ( n, (*ufd)->fd );
  17.656 +            ufd = &(*ufd)->next;
  17.657 +        }
  17.658 +        
  17.659 +        /* control and data fds: */
  17.660 +        con = &connection_list;
  17.661 +        while ((*con) != NULL)
  17.662 +        {
  17.663 +            if ((*con)->ctrl_fd > 0)
  17.664 +            {
  17.665 +                FD_SET ( (*con)->ctrl_fd, &rd );
  17.666 +                n = fd_max ( n, (*con)->ctrl_fd );
  17.667 +            }
  17.668 +            if ((*con)->data_fd > 0)
  17.669 +            {
  17.670 +                FD_SET ( (*con)->data_fd, &rd );
  17.671 +                n = fd_max ( n, (*con)->data_fd );
  17.672 +            }
  17.673 +            con = &(*con)->next;
  17.674 +        }
  17.675 +        
  17.676 +        ret = select ( n + 1, &rd, &wr, &er, &timeout );
  17.677 +        
  17.678 +        if ( (timeout.tv_sec == 0) && (timeout.tv_usec == 0) )
  17.679 +        {
  17.680 +            gc_ufd_list(&unbound_fd_list);
  17.681 +            gc_connection_list();
  17.682 +            timeout.tv_sec = XCS_GC_INTERVAL;
  17.683 +        }
  17.684 +        
  17.685 +        if ( (ret == -1) && (errno == EINTR) )
  17.686 +            continue;
  17.687 +        if ( ret < 0 )
  17.688 +        {
  17.689 +            perror ("select()");
  17.690 +            exit(-1);
  17.691 +        }
  17.692 +        
  17.693 +        /* CASE 1: Events arriving on /dev/evtchn. */
  17.694 +        
  17.695 +        if ( FD_ISSET (evtchn_fd, &rd ))
  17.696 +            handle_ctrl_if();
  17.697 +        
  17.698 +        /* CASE 2: New connection on the listen port. */
  17.699 +        if ( FD_ISSET ( listen_fd, &rd ))
  17.700 +        {
  17.701 +            struct sockaddr_in remote_addr;
  17.702 +            int size;
  17.703 +            memset (&remote_addr, 0, sizeof (remote_addr));
  17.704 +            size = sizeof remote_addr;
  17.705 +            ret = accept(listen_fd, (struct sockaddr *)&remote_addr, &size);
  17.706 +            if ( ret < 0 )
  17.707 +            {
  17.708 +                perror("accept()");
  17.709 +            } else {
  17.710 +                unbound_fd_t *new_ufd;
  17.711 +                
  17.712 +                new_ufd = (unbound_fd_t *)malloc(sizeof(*new_ufd));
  17.713 +                
  17.714 +                if (new_ufd != NULL)
  17.715 +                {
  17.716 +                    gettimeofday(&new_ufd->born, NULL);
  17.717 +                    new_ufd->fd     = ret;
  17.718 +                    new_ufd->next   = unbound_fd_list;
  17.719 +                    unbound_fd_list = new_ufd; 
  17.720 +                } else {
  17.721 +                    perror("malloc unbound connection");
  17.722 +                    close(ret);
  17.723 +                }
  17.724 +            }
  17.725 +        }
  17.726 +        
  17.727 +        /* CASE 3a: Handle messages on control connections. */
  17.728 +        
  17.729 +        con = &connection_list;
  17.730 +        while ( *con != NULL )
  17.731 +        {
  17.732 +            if ( ((*con)->ctrl_fd > 0) && (FD_ISSET((*con)->ctrl_fd, &rd)) )
  17.733 +            {
  17.734 +                xcs_msg_t msg;
  17.735 +                memset (&msg, 0, sizeof(msg));
  17.736 +                ret = read( (*con)->ctrl_fd, &msg, sizeof(msg) );
  17.737 +                
  17.738 +                if ( ret < 0 )
  17.739 +                {
  17.740 +                    perror("reading ctrl fd.");
  17.741 +                } else if ( ret == 0 )
  17.742 +                {
  17.743 +                    DPRINTF("Control connection dropped.\n");
  17.744 +                    close ( (*con)->ctrl_fd );
  17.745 +                    (*con)->ctrl_fd = -1;
  17.746 +                    gettimeofday(&(*con)->disconnect_time, NULL);
  17.747 +                } else 
  17.748 +                {
  17.749 +                    if ( ret != sizeof(msg) )
  17.750 +                    {
  17.751 +                        DPRINTF("Unexpected frame size!\n");
  17.752 +                        continue;
  17.753 +                    }
  17.754 +                    
  17.755 +                    ret = handle_control_message( *con, &msg );
  17.756 +                    
  17.757 +                    if ( ret == 1 )
  17.758 +                        send( (*con)->ctrl_fd, &msg, sizeof(msg), 0 );
  17.759 +                }
  17.760 +            }
  17.761 +            con = &(*con)->next;
  17.762 +        }
  17.763 +        
  17.764 +        /* CASE 3b: Handle messages on data connections. */
  17.765 +        
  17.766 +        con = &connection_list;
  17.767 +        while ( *con != NULL )
  17.768 +        {
  17.769 +            if ( ((*con)->data_fd > 0) && (FD_ISSET((*con)->data_fd, &rd)) )
  17.770 +            {
  17.771 +                xcs_msg_t msg;
  17.772 +                memset (&msg, 0, sizeof(msg));
  17.773 +                ret = read( (*con)->data_fd, &msg, sizeof(msg) );
  17.774 +                
  17.775 +                if ( ret < 0 )
  17.776 +                {
  17.777 +                    perror("reading data fd.");
  17.778 +                } else if ( ret == 0 )
  17.779 +                {
  17.780 +                    DPRINTF("Data connection dropped.\n");
  17.781 +                    close ( (*con)->data_fd );
  17.782 +                    (*con)->data_fd = -1;
  17.783 +                    gettimeofday(&(*con)->disconnect_time, NULL);
  17.784 +                } else 
  17.785 +                {
  17.786 +                    if ( ret != sizeof(msg) )
  17.787 +                    {
  17.788 +                        DPRINTF("Unexpected frame size!\n");
  17.789 +                        continue;
  17.790 +                    }
  17.791 +                    
  17.792 +                    handle_data_message( *con, &msg );
  17.793 +                }
  17.794 +            }
  17.795 +            con = &(*con)->next;
  17.796 +        }
  17.797 +        
  17.798 +        /* CASE 3c: Handle messages arriving on unbound connections. */
  17.799 +        ufd = &unbound_fd_list;
  17.800 +        while ((*ufd) != NULL)
  17.801 +        {
  17.802 +            if ( FD_ISSET( (*ufd)->fd, &rd ) )
  17.803 +            {
  17.804 +                xcs_msg_t msg;
  17.805 +                memset (&msg, 0, sizeof(msg));
  17.806 +                ret = read( (*ufd)->fd, &msg, sizeof(msg) );
  17.807 +                
  17.808 +                if ( ret == 0 )
  17.809 +                {
  17.810 +                    close ( (*ufd)->fd );
  17.811 +                    delete_ufd(ufd);
  17.812 +                    continue; /* we just advanced ufd */
  17.813 +                } else {
  17.814 +                    if ( ret != sizeof(msg) )
  17.815 +                    {
  17.816 +                        DPRINTF("Unexpected frame size!\n");
  17.817 +                        continue;
  17.818 +                    }
  17.819 +                    
  17.820 +                    ret = handle_connect_msg( &msg, (*ufd)->fd );
  17.821 +                    
  17.822 +                    if ( (ret == CONNECTED) || (ret == NO_CHANGE) )
  17.823 +                        send( (*ufd)->fd, &msg, sizeof(msg), 0 );
  17.824 +                    
  17.825 +                    if ( (ret = CONNECTED) || (ret = DISCONNECTED) )
  17.826 +                    {
  17.827 +                        delete_ufd( ufd );
  17.828 +                        continue;
  17.829 +                    }
  17.830 +                }
  17.831 +            }
  17.832 +            ufd = &(*ufd)->next;
  17.833 +        }
  17.834 +    }
  17.835 +}
  17.836 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/xcs/xcs.h	Fri Dec 31 17:26:00 2004 +0000
    18.3 @@ -0,0 +1,155 @@
    18.4 +/* xcs.h
    18.5 + *
    18.6 + * public interfaces for the control interface switch (xcs).
    18.7 + *
    18.8 + * (c) 2004, Andrew Warfield
    18.9 + *
   18.10 + */
   18.11 +
   18.12 +
   18.13 +#ifndef __XCS_H__
   18.14 +#define __XCS_H__
   18.15 +
   18.16 +#include <pthread.h>
   18.17 +#include <xc.h>
   18.18 +#include <xen/xen.h>
   18.19 +#include <xen/io/domain_controller.h>
   18.20 +#include <xen/linux/privcmd.h>
   18.21 +#include <sys/time.h>
   18.22 +#include "xcs_proto.h"
   18.23 +
   18.24 +/* ------[ Debug macros ]--------------------------------------------------*/
   18.25 +
   18.26 +#if 0
   18.27 +#define DPRINTF(_f, _a...) printf ( _f , ## _a )
   18.28 +#else
   18.29 +#define DPRINTF(_f, _a...) ((void)0)
   18.30 +#endif
   18.31 +
   18.32 +/* ------[ XCS-specific defines and types ]--------------------------------*/
   18.33 +
   18.34 +#define MAX_DOMS            1024
   18.35 +#define XCS_SESSION_TIMEOUT   10 /* (secs) disconnected session gc timeout */
   18.36 +#define XCS_UFD_TIMEOUT        5 /* how long can connections be unbound?   */
   18.37 +#define XCS_GC_INTERVAL        5 /* How often to run gc handlers.          */
   18.38 +
   18.39 +
   18.40 +/* ------[ Other required defines ]----------------------------------------*/
   18.41 +
   18.42 +/* Size of a machine page frame. */
   18.43 +#define PAGE_SIZE 4096
   18.44 +
   18.45 +#if defined(__i386__)
   18.46 +#define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
   18.47 +#define wmb() __asm__ __volatile__ ( "" : : : "memory" )
   18.48 +#else
   18.49 +#error "Define barriers"
   18.50 +#endif
   18.51 +
   18.52 +#ifndef timersub /* XOPEN and __BSD don't cooperate well... */
   18.53 +#define timersub(a, b, result)                                                \
   18.54 +  do {                                                                        \
   18.55 +    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
   18.56 +    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
   18.57 +    if ((result)->tv_usec < 0) {                                              \
   18.58 +      --(result)->tv_sec;                                                     \
   18.59 +      (result)->tv_usec += 1000000;                                           \
   18.60 +    }                                                                         \
   18.61 +  } while (0)
   18.62 +#endif /*timersub*/
   18.63 +
   18.64 +/* ------[ Bindings Interface ]--------------------------------------------*/
   18.65 +
   18.66 +/*forward declare connection_t */
   18.67 +typedef struct connection_st connection_t;
   18.68 +
   18.69 +typedef struct {
   18.70 +    int    port;
   18.71 +    u16    type;
   18.72 +} binding_key_t;
   18.73 +
   18.74 +typedef struct binding_key_ent_st {
   18.75 +    binding_key_t              key;
   18.76 +    struct binding_key_ent_st *next;
   18.77 +} binding_key_ent_t;
   18.78 +
   18.79 +#define BINDING_KEYS_EQUAL(_k1, _k2) \
   18.80 +    (((_k1)->port == (_k2)->port) && ((_k1)->type == (_k2)->type))
   18.81 +
   18.82 +int  xcs_bind(connection_t *con, int port, u16 type);
   18.83 +int  xcs_unbind(connection_t *con, int port, u16 type);
   18.84 +void xcs_lookup(int port, u16 type, void (*f)(connection_t *, void *), 
   18.85 +        void *arg);
   18.86 +void init_bindings(void);
   18.87 +
   18.88 +/* ------[ Connection Interface ]------------------------------------------*/
   18.89 +
   18.90 +struct connection_st {
   18.91 +    unsigned long      id;              /* Unique session id             */
   18.92 +    int                ctrl_fd;         /* TCP descriptors               */
   18.93 +    int                data_fd;         /*                               */
   18.94 +    binding_key_ent_t *bindings;        /* List of bindings              */
   18.95 +    connection_t      *next;            /* Linked list of connections    */
   18.96 +    struct timeval     disconnect_time; /*  "            "               */
   18.97 +}; /* previously typedefed as connection_t */
   18.98 +
   18.99 +
  18.100 +extern connection_t *connection_list;
  18.101 +
  18.102 +connection_t *get_con_by_session(unsigned long session_id);
  18.103 +connection_t *connection_new();
  18.104 +void connection_free(connection_t *con);
  18.105 +int  connection_add_binding(connection_t *con, binding_key_t *key);
  18.106 +int  connection_remove_binding(connection_t *con, binding_key_t *key);
  18.107 +int  connection_has_binding(connection_t *con, binding_key_t *key);
  18.108 +void gc_connection_list(void);
  18.109 +
  18.110 +/* ------[ Control Channel Interfaces ]------------------------------------*/
  18.111 + 
  18.112 +typedef struct {
  18.113 +    int               connected;
  18.114 +    int               ref_count;
  18.115 +    int               type;
  18.116 +    u32               remote_dom;
  18.117 +    int               local_port;
  18.118 +    int               remote_port;
  18.119 +    control_if_t     *interface;
  18.120 +    ctrl_back_ring_t  tx_ring;
  18.121 +    ctrl_front_ring_t rx_ring;
  18.122 +    int               virq;
  18.123 +} control_channel_t;
  18.124 +
  18.125 +/* cc types that we care about */
  18.126 +#define CC_TYPE_INTERDOMAIN  0
  18.127 +#define CC_TYPE_VIRQ         1
  18.128 +
  18.129 +control_channel_t 
  18.130 +     *ctrl_chan_new(u32 dom, int local_port, int remote_port);
  18.131 +void  ctrl_chan_free(control_channel_t *cc);
  18.132 +int   ctrl_chan_init(void);
  18.133 +int   ctrl_chan_notify(control_channel_t *cc);
  18.134 +int   ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *);
  18.135 +int   ctrl_chan_write_request(control_channel_t *cc, 
  18.136 +                            xcs_control_msg_t *smsg);
  18.137 +int   ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *);
  18.138 +int   ctrl_chan_write_response(control_channel_t *cc, 
  18.139 +                             xcs_control_msg_t *smsg);
  18.140 +int   ctrl_chan_request_to_read(control_channel_t *cc);
  18.141 +int   ctrl_chan_space_to_write_request(control_channel_t *cc);
  18.142 +int   ctrl_chan_response_to_read(control_channel_t *cc);
  18.143 +int   ctrl_chan_space_to_write_response(control_channel_t *cc);
  18.144 +int   ctrl_chan_connect(control_channel_t *cc);
  18.145 +void  ctrl_chan_disconnect(control_channel_t *cc);
  18.146 +int   ctrl_chan_bind_virq(int virq, int *port);
  18.147 +
  18.148 +/* ------[ Event notification interfaces ]---------------------------------*/
  18.149 +
  18.150 +
  18.151 +int   evtchn_open(void);
  18.152 +void  evtchn_close();
  18.153 +int   evtchn_bind(int idx);
  18.154 +int   evtchn_unbind(int idx);
  18.155 +void  evtchn_unmask(u16 idx);
  18.156 +int   evtchn_read();
  18.157 +
  18.158 +#endif /* __XCS_H__ */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/xcs/xcs_proto.h	Fri Dec 31 17:26:00 2004 +0000
    19.3 @@ -0,0 +1,101 @@
    19.4 +/* xcs_proto.h
    19.5 + *
    19.6 + * protocol interfaces for the control interface switch (xcs).
    19.7 + *
    19.8 + * (c) 2004, Andrew Warfield
    19.9 + *
   19.10 + */
   19.11 +
   19.12 +#ifndef  __XCS_PROTO_H__
   19.13 +#define  __XCS_PROTO_H__
   19.14 +
   19.15 +#define XCS_TCP_PORT     1633
   19.16 +
   19.17 +/* xcs message types: */
   19.18 +#define XCS_CONNECT_CTRL       0 /* This is a control connection.     */
   19.19 +#define XCS_CONNECT_DATA       1 /* This is a data connection.        */
   19.20 +#define XCS_CONNECT_BYE        2 /* Terminate a session.              */
   19.21 +#define XCS_MSG_BIND           3 /* Register for a message type.      */
   19.22 +#define XCS_MSG_UNBIND         4 /* Unregister for a message type.    */
   19.23 +#define XCS_VIRQ_BIND          5 /* Register for a virq.              */
   19.24 +#define XCS_MSG_WRITELOCK      6 /* Writelock a (dom,type) pair.      */
   19.25 +#define XCS_CIF_NEW_CC         7 /* Create a new control channel.     */
   19.26 +#define XCS_CIF_FREE_CC        8 /* Create a new control channel.     */
   19.27 +#define XCS_REQUEST            9 /* This is a request message.        */
   19.28 +#define XCS_RESPONSE          10 /* this is a response Message.       */
   19.29 +#define XCS_VIRQ              11 /* this is a virq notification.      */
   19.30 +
   19.31 +/* xcs result values: */
   19.32 +#define XCS_RSLT_OK            0
   19.33 +#define XCS_RSLT_FAILED        1 /* something bad happened.           */
   19.34 +#define XCS_RSLT_ARECONNECTED  2 /* attempt to over connect.          */
   19.35 +#define XCS_RSLT_BADSESSION    3 /* request for unknown session id.   */
   19.36 +#define XCS_RSLT_NOSESSION     4 /* tried to do something before NEW. */
   19.37 +#define XCS_RSLT_CONINUSE      5 /* Requested connection is taken.    */
   19.38 +#define XCS_RSLT_BADREQUEST    6 /* Request message didn't validate.  */
   19.39 +
   19.40 +/* Binding wildcards */
   19.41 +#define PORT_WILDCARD  0xefffffff
   19.42 +#define TYPE_WILDCARD  0xffff
   19.43 +#define TYPE_VIRQ      0xfffe
   19.44 +
   19.45 +typedef struct {
   19.46 +    u32 session_id;
   19.47 +} xcs_connect_msg_t;
   19.48 +
   19.49 +typedef struct {
   19.50 +    int port;
   19.51 +    u16 type;  
   19.52 +} xcs_bind_msg_t;
   19.53 +
   19.54 +typedef struct {
   19.55 +    int port;
   19.56 +    u16 virq;  
   19.57 +} xcs_virq_msg_t;
   19.58 +
   19.59 +typedef struct {
   19.60 +    u32 dom;
   19.61 +    int local_port;
   19.62 +    int remote_port;
   19.63 +} xcs_interface_msg_t;
   19.64 +
   19.65 +typedef struct {
   19.66 +    u32           remote_dom;
   19.67 +    int           local_port;
   19.68 +    control_msg_t msg;
   19.69 +} xcs_control_msg_t;
   19.70 +
   19.71 +typedef struct {
   19.72 +    u32 type;
   19.73 +    u32 result;
   19.74 +    union {
   19.75 +        xcs_connect_msg_t   connect;   /* These are xcs ctrl message types */
   19.76 +        xcs_bind_msg_t      bind;
   19.77 +        xcs_virq_msg_t      virq;
   19.78 +        xcs_interface_msg_t interface;
   19.79 +        
   19.80 +        xcs_control_msg_t   control;   /* These are xcs data message types */
   19.81 +    } PACKED u;
   19.82 +} xcs_msg_t;
   19.83 +
   19.84 +/* message validation macros. */
   19.85 +#define PORT_VALID(_p)                                                 \
   19.86 +    ( (((_p) >= 0) && ((_p) < NR_EVENT_CHANNELS))                      \
   19.87 +    || ((_p) == PORT_WILDCARD) )
   19.88 +
   19.89 +#define TYPE_VALID(_t)                                                 \
   19.90 +    (  ((_t) < 256)                                                    \
   19.91 +    || ((_t) == TYPE_VIRQ)                                             \
   19.92 +    || ((_t) == TYPE_WILDCARD) )
   19.93 +
   19.94 +#define BIND_MSG_VALID(_b)                                             \
   19.95 +    ( PORT_VALID((_b)->port) && TYPE_VALID((_b)->type) )
   19.96 +    
   19.97 +/* Port is overwritten, and we don't currently validate the requested virq. */
   19.98 +#define VIRQ_MSG_VALID(_v) ( 1 )
   19.99 +    
  19.100 +/* Interfaces may return with ports of -1, but may not be requested as such */
  19.101 +#define INTERFACE_MSG_VALID(_i)                                        \
  19.102 +    ( PORT_VALID((_i)->local_port) && PORT_VALID((_i)->remote_port) )
  19.103 +
  19.104 +#endif /* __XCS_PROTO_H__ */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/xcs/xcsdump.c	Fri Dec 31 17:26:00 2004 +0000
    20.3 @@ -0,0 +1,182 @@
    20.4 +/* xcsdump.c
    20.5 + *
    20.6 + * little tool to sniff control messages.
    20.7 + *
    20.8 + * Copyright (c) 2004, Andrew Warfield
    20.9 + */
   20.10 +
   20.11 +#include <stdio.h>
   20.12 +#include <stdlib.h>
   20.13 +#include <string.h>
   20.14 +#include <unistd.h>
   20.15 +#include <sys/types.h>
   20.16 +#include <sys/socket.h>
   20.17 +#include <netinet/in.h>
   20.18 +#include <arpa/inet.h>
   20.19 +#include <ctype.h>
   20.20 +#include <xc.h>
   20.21 +#include <xen/xen.h>
   20.22 +#include <xen/io/domain_controller.h>
   20.23 +#include "xcs_proto.h"
   20.24 +#include "xcs.h"
   20.25 +
   20.26 +static int xcs_ctrl_fd = -1; /* connection to the xcs server. */
   20.27 +static int xcs_data_fd = -1; /* connection to the xcs server. */
   20.28 +
   20.29 +int tcp_connect(char *ip, short port)
   20.30 +{
   20.31 +    struct sockaddr_in addr;
   20.32 +    int ret, fd;
   20.33 +
   20.34 +    fd = socket(AF_INET, SOCK_STREAM, 0);
   20.35 +    if (fd < 0)
   20.36 +    {
   20.37 +        printf("error creating xcs socket!\n");
   20.38 +        return -1;
   20.39 +    }
   20.40 +
   20.41 +    addr.sin_family = AF_INET;
   20.42 +    addr.sin_port = htons(port);
   20.43 +    addr.sin_addr.s_addr = inet_addr(ip);
   20.44 +    memset(&(addr.sin_zero), '\0', 8);
   20.45 +
   20.46 +    ret = connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr));
   20.47 +    if (ret < 0) 
   20.48 +    {
   20.49 +        printf("error connecting to xcs!\n");
   20.50 +        return -1;
   20.51 +    }
   20.52 +    
   20.53 +    return fd;
   20.54 +}
   20.55 +
   20.56 +void tcp_disconnect(int *fd)
   20.57 +{
   20.58 +    close(*fd);
   20.59 +    *fd = -1;
   20.60 +}
   20.61 +
   20.62 +void xcs_read(int fd, xcs_msg_t *msg)
   20.63 +{
   20.64 +    int ret;
   20.65 +    
   20.66 +    ret = read(fd, msg, sizeof(xcs_msg_t));
   20.67 +    if (ret != sizeof(xcs_msg_t)) {
   20.68 +        printf("read error\n");
   20.69 +        exit(-1);
   20.70 +    }
   20.71 +}
   20.72 +
   20.73 +void xcs_send(int fd, xcs_msg_t *msg)
   20.74 +{
   20.75 +    int ret;
   20.76 +    
   20.77 +    ret = send(fd, msg, sizeof(xcs_msg_t), 0);
   20.78 +    if (ret != sizeof(xcs_msg_t) )
   20.79 +    {
   20.80 +        printf("send error\n");
   20.81 +        exit(-1);
   20.82 +    }
   20.83 +}
   20.84 +              
   20.85 +
   20.86 +int main(int argc, char* argv[])
   20.87 +{
   20.88 +    int ret, i;
   20.89 +    xcs_msg_t msg;
   20.90 +    control_msg_t *cmsg;
   20.91 +    int verbose = 0;
   20.92 +    
   20.93 +    if (argc > 1) 
   20.94 +        if ((strlen(argv[1]) >=2) && (strncmp(argv[1], "-v", 2) == 0))
   20.95 +            verbose = 1;
   20.96 +    
   20.97 +    ret = tcp_connect("127.0.0.1", XCS_TCP_PORT);
   20.98 +    if (ret < 0) 
   20.99 +    {
  20.100 +        printf("connect failed!\n"); 
  20.101 +        exit(-1);
  20.102 +    }
  20.103 +    xcs_ctrl_fd = ret;
  20.104 +    
  20.105 +    memset(&msg, 0, sizeof(msg));
  20.106 +    msg.type = XCS_CONNECT_CTRL;
  20.107 +    xcs_send(xcs_ctrl_fd, &msg);
  20.108 +    xcs_read(xcs_ctrl_fd, &msg);
  20.109 +    if (msg.result != XCS_RSLT_OK)
  20.110 +    {
  20.111 +        printf("Error connecting control channel\n");
  20.112 +        exit(-1);
  20.113 +    }
  20.114 +    
  20.115 +    ret = tcp_connect("127.0.0.1", XCS_TCP_PORT);
  20.116 +    if (ret < 0) 
  20.117 +    {
  20.118 +        printf("connect failed!\n"); 
  20.119 +        exit(-1);
  20.120 +    }
  20.121 +    xcs_data_fd = ret;
  20.122 +    
  20.123 +    msg.type = XCS_CONNECT_DATA;
  20.124 +    /* session id is set from before... */
  20.125 +    xcs_send(xcs_data_fd, &msg);
  20.126 +    xcs_read(xcs_data_fd, &msg);
  20.127 +    if (msg.result != XCS_RSLT_OK)
  20.128 +    {
  20.129 +        printf("Error connecting data channel\n");
  20.130 +        exit(-1);
  20.131 +    }
  20.132 +    
  20.133 +    msg.type = XCS_MSG_BIND;
  20.134 +    msg.u.bind.port = PORT_WILDCARD;
  20.135 +    msg.u.bind.type = TYPE_WILDCARD;
  20.136 +    xcs_send(xcs_ctrl_fd, &msg);
  20.137 +    xcs_read(xcs_ctrl_fd, &msg);
  20.138 +    if (msg.result != XCS_RSLT_OK)
  20.139 +    {
  20.140 +        printf("Error binding.\n");
  20.141 +        exit(-1);
  20.142 +    }
  20.143 +    
  20.144 +    
  20.145 +    while (1)
  20.146 +    {
  20.147 +        xcs_read(xcs_data_fd, &msg);
  20.148 +        cmsg = &msg.u.control.msg;
  20.149 +        
  20.150 +        for (i=0; i<60; i++)
  20.151 +            if ((!isprint(cmsg->msg[i])) && (cmsg->msg[i] != '\0'))
  20.152 +                cmsg->msg[i] = '.';
  20.153 +        cmsg->msg[59] = '\0';
  20.154 +        
  20.155 +        switch (msg.type)
  20.156 +        {
  20.157 +        case XCS_REQUEST:
  20.158 +            printf("[REQUEST ] : (dom:%u port:%d) (type:(%d,%d) len %d) \n",
  20.159 +                    msg.u.control.remote_dom,
  20.160 +                    msg.u.control.local_port,
  20.161 +                    msg.u.control.msg.type, 
  20.162 +                    msg.u.control.msg.subtype, 
  20.163 +                    msg.u.control.msg.length);
  20.164 +            if (verbose)
  20.165 +                printf("           : %s\n", msg.u.control.msg.msg);
  20.166 +            break; 
  20.167 +        case XCS_RESPONSE:
  20.168 +            printf("[RESPONSE] : (dom:%u port:%d) (type:(%d,%d) len %d) \n",
  20.169 +                    msg.u.control.remote_dom,
  20.170 +                    msg.u.control.local_port,
  20.171 +                    msg.u.control.msg.type, 
  20.172 +                    msg.u.control.msg.subtype, 
  20.173 +                    msg.u.control.msg.length);
  20.174 +            if (verbose)
  20.175 +                printf("           : %s\n", msg.u.control.msg.msg);
  20.176 +            break;
  20.177 +        case XCS_VIRQ:
  20.178 +            printf("[VIRQ    ] : %d\n", msg.u.control.local_port);
  20.179 +        default:
  20.180 +            printf("[UNKNOWN ]\n");
  20.181 +        }
  20.182 +    }
  20.183 +    
  20.184 +    return(0);
  20.185 +}
    21.1 --- a/xen/include/public/io/domain_controller.h	Fri Dec 31 13:53:32 2004 +0000
    21.2 +++ b/xen/include/public/io/domain_controller.h	Fri Dec 31 17:26:00 2004 +0000
    21.3 @@ -10,6 +10,7 @@
    21.4  #ifndef __XEN_PUBLIC_IO_DOMAIN_CONTROLLER_H__
    21.5  #define __XEN_PUBLIC_IO_DOMAIN_CONTROLLER_H__
    21.6  
    21.7 +#include "ring.h"
    21.8  
    21.9  /*
   21.10   * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
   21.11 @@ -33,15 +34,24 @@ typedef struct {
   21.12      u8 msg[60];  /*  4: type-specific message data */
   21.13  } PACKED control_msg_t; /* 64 bytes */
   21.14  
   21.15 +/* These are used by the control message deferred ring. */
   21.16  #define CONTROL_RING_SIZE 8
   21.17  typedef u32 CONTROL_RING_IDX;
   21.18  #define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
   21.19  
   21.20 +/*
   21.21 + * Generate control ring structures and types.
   21.22 + *
   21.23 + * CONTROL_RING_MEM is currently an 8-slot ring of ctrl_msg_t structs and
   21.24 + * two 32-bit counters:  (64 * 8) + (2 * 4) = 520
   21.25 + */
   21.26 +#define CONTROL_RING_MEM 520 
   21.27 +#define CTRL_RING RING_PARAMS(control_msg_t, control_msg_t, CONTROL_RING_MEM)
   21.28 +DEFINE_RING_TYPES(ctrl, CTRL_RING);
   21.29 +
   21.30  typedef struct {
   21.31 -    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
   21.32 -    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
   21.33 -    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
   21.34 -    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
   21.35 +    ctrl_sring_t tx_ring; /*    0: guest -> controller  */
   21.36 +    ctrl_sring_t rx_ring; /*  520: controller -> guest  */
   21.37  } PACKED control_if_t; /* 1040 bytes */
   21.38  
   21.39  /*