ia64/xen-unstable

changeset 3965:f16176a68244

bitkeeper revision 1.1236.1.46 (4225fdb2Fsz5LfXWKyVON4u_POTHkQ)

Credit-based rate limiting in net backend. From Ross Mcilroy.
Signed-off-by: Keir Fraser <keir.fraser@cl.cam.ac.uk>
author kaf24@scramble.cl.cam.ac.uk
date Wed Mar 02 17:53:54 2005 +0000 (2005-03-02)
parents 180fe147132c
children 0b9ff7354a95
files linux-2.6.10-xen-sparse/drivers/xen/netback/common.h linux-2.6.10-xen-sparse/drivers/xen/netback/control.c linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c tools/python/xen/lowlevel/xu/xu.c tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/messages.py tools/python/xen/xend/server/netif.py tools/python/xen/xm/main.py xen/include/public/io/domain_controller.h
line diff
     1.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/netback/common.h	Wed Mar 02 09:33:11 2005 +0000
     1.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/netback/common.h	Wed Mar 02 17:53:54 2005 +0000
     1.3 @@ -78,6 +78,7 @@ typedef struct netif_st {
     1.4  
     1.5  void netif_create(netif_be_create_t *create);
     1.6  void netif_destroy(netif_be_destroy_t *destroy);
     1.7 +void netif_creditlimit(netif_be_creditlimit_t *creditlimit);
     1.8  void netif_connect(netif_be_connect_t *connect);
     1.9  int  netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
    1.10  void netif_disconnect_complete(netif_t *netif);
     2.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/netback/control.c	Wed Mar 02 09:33:11 2005 +0000
     2.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/netback/control.c	Wed Mar 02 17:53:54 2005 +0000
     2.3 @@ -21,12 +21,17 @@ static void netif_ctrlif_rx(ctrl_msg_t *
     2.4          if ( msg->length != sizeof(netif_be_destroy_t) )
     2.5              goto parse_error;
     2.6          netif_destroy((netif_be_destroy_t *)&msg->msg[0]);
     2.7 -        break;        
     2.8 +        break;  
     2.9 +    case CMSG_NETIF_BE_CREDITLIMIT:
    2.10 +        if ( msg->length != sizeof(netif_be_creditlimit_t) )
    2.11 +            goto parse_error;
    2.12 +        netif_creditlimit((netif_be_creditlimit_t *)&msg->msg[0]);
    2.13 +        break;       
    2.14      case CMSG_NETIF_BE_CONNECT:
    2.15          if ( msg->length != sizeof(netif_be_connect_t) )
    2.16              goto parse_error;
    2.17          netif_connect((netif_be_connect_t *)&msg->msg[0]);
    2.18 -        break;        
    2.19 +        break; 
    2.20      case CMSG_NETIF_BE_DISCONNECT:
    2.21          if ( msg->length != sizeof(netif_be_disconnect_t) )
    2.22              goto parse_error;
     3.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c	Wed Mar 02 09:33:11 2005 +0000
     3.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c	Wed Mar 02 17:53:54 2005 +0000
     3.3 @@ -3,7 +3,7 @@
     3.4   * 
     3.5   * Network-device interface management.
     3.6   * 
     3.7 - * Copyright (c) 2004, Keir Fraser
     3.8 + * Copyright (c) 2004-2005, Keir Fraser
     3.9   */
    3.10  
    3.11  #include "common.h"
    3.12 @@ -140,7 +140,7 @@ void netif_create(netif_be_create_t *cre
    3.13  
    3.14      netif->credit_bytes = netif->remaining_credit = ~0UL;
    3.15      netif->credit_usec  = 0UL;
    3.16 -    /*init_ac_timer(&new_vif->credit_timeout);*/
    3.17 +    init_timer(&netif->credit_timeout);
    3.18  
    3.19      pnetif = &netif_hash[NETIF_HASH(domid, handle)];
    3.20      while ( *pnetif != NULL )
    3.21 @@ -234,6 +234,38 @@ void netif_destroy(netif_be_destroy_t *d
    3.22      destroy->status = NETIF_BE_STATUS_OKAY;
    3.23  }
    3.24  
    3.25 +void netif_creditlimit(netif_be_creditlimit_t *creditlimit)
    3.26 +{
    3.27 +    domid_t       domid  = creditlimit->domid;
    3.28 +    unsigned int  handle = creditlimit->netif_handle;
    3.29 +    netif_t      *netif;
    3.30 +
    3.31 +    netif = netif_find_by_handle(domid, handle);
    3.32 +    if ( unlikely(netif == NULL) )
    3.33 +    {
    3.34 +        DPRINTK("netif_creditlimit attempted for non-existent netif"
    3.35 +                " (%u,%u)\n", creditlimit->domid, creditlimit->netif_handle); 
    3.36 +        creditlimit->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
    3.37 +        return; 
    3.38 +    }
    3.39 +
    3.40 +    /* Set the credit limit (reset remaining credit to new limit). */
    3.41 +    netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes;
    3.42 +    netif->credit_usec = creditlimit->period_usec;
    3.43 +
    3.44 +    if ( netif->status == CONNECTED )
    3.45 +    {
    3.46 +        /*
    3.47 +         * Schedule work so that any packets waiting under previous credit 
    3.48 +         * limit are dealt with (acts like a replenishment point).
    3.49 +         */
    3.50 +        netif->credit_timeout.expires = jiffies;
    3.51 +        netif_schedule_work(netif);
    3.52 +    }
    3.53 +    
    3.54 +    creditlimit->status = NETIF_BE_STATUS_OKAY;
    3.55 +}
    3.56 +
    3.57  void netif_connect(netif_be_connect_t *connect)
    3.58  {
    3.59      domid_t       domid  = connect->domid;
    3.60 @@ -245,9 +277,6 @@ void netif_connect(netif_be_connect_t *c
    3.61      pgprot_t      prot;
    3.62      int           error;
    3.63      netif_t      *netif;
    3.64 -#if 0
    3.65 -    struct net_device *eth0_dev;
    3.66 -#endif
    3.67  
    3.68      netif = netif_find_by_handle(domid, handle);
    3.69      if ( unlikely(netif == NULL) )
     4.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c	Wed Mar 02 09:33:11 2005 +0000
     4.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c	Wed Mar 02 17:53:54 2005 +0000
     4.3 @@ -7,7 +7,7 @@
     4.4   * reference front-end implementation can be found in:
     4.5   *  drivers/xen/netfront/netfront.c
     4.6   * 
     4.7 - * Copyright (c) 2002-2004, K A Fraser
     4.8 + * Copyright (c) 2002-2005, K A Fraser
     4.9   */
    4.10  
    4.11  #include "common.h"
    4.12 @@ -380,14 +380,13 @@ void netif_deschedule_work(netif_t *neti
    4.13      remove_from_net_schedule_list(netif);
    4.14  }
    4.15  
    4.16 -#if 0
    4.17 +
    4.18  static void tx_credit_callback(unsigned long data)
    4.19  {
    4.20      netif_t *netif = (netif_t *)data;
    4.21      netif->remaining_credit = netif->credit_bytes;
    4.22      netif_schedule_work(netif);
    4.23  }
    4.24 -#endif
    4.25  
    4.26  static void net_tx_action(unsigned long unused)
    4.27  {
    4.28 @@ -471,42 +470,48 @@ static void net_tx_action(unsigned long 
    4.29              continue;
    4.30          }
    4.31  
    4.32 -        netif->tx->req_cons = ++netif->tx_req_cons;
    4.33 -
    4.34 -        /*
    4.35 -         * 1. Ensure that we see the request when we copy it.
    4.36 -         * 2. Ensure that frontend sees updated req_cons before we check
    4.37 -         *    for more work to schedule.
    4.38 -         */
    4.39 -        mb();
    4.40 -
    4.41 +        rmb(); /* Ensure that we see the request before we copy it. */
    4.42          memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, 
    4.43                 sizeof(txreq));
    4.44  
    4.45 -#if 0
    4.46          /* Credit-based scheduling. */
    4.47 -        if ( tx.size > netif->remaining_credit )
    4.48 +        if ( txreq.size > netif->remaining_credit )
    4.49          {
    4.50 -            s_time_t now = NOW(), next_credit = 
    4.51 -                netif->credit_timeout.expires + MICROSECS(netif->credit_usec);
    4.52 -            if ( next_credit <= now )
    4.53 +            unsigned long now = jiffies;
    4.54 +            unsigned long next_credit = 
    4.55 +                netif->credit_timeout.expires +
    4.56 +                msecs_to_jiffies(netif->credit_usec / 1000);
    4.57 +
    4.58 +            /* Timer could already be pending in some rare cases. */
    4.59 +            if ( timer_pending(&netif->credit_timeout) )
    4.60 +                break;
    4.61 +
    4.62 +            /* Already passed the point at which we can replenish credit? */
    4.63 +            if ( time_after_eq(now, next_credit) )
    4.64              {
    4.65                  netif->credit_timeout.expires = now;
    4.66                  netif->remaining_credit = netif->credit_bytes;
    4.67              }
    4.68 -            else
    4.69 +
    4.70 +            /* Still too big to send right now? Then set a timer callback. */
    4.71 +            if ( txreq.size > netif->remaining_credit )
    4.72              {
    4.73                  netif->remaining_credit = 0;
    4.74                  netif->credit_timeout.expires  = next_credit;
    4.75                  netif->credit_timeout.data     = (unsigned long)netif;
    4.76                  netif->credit_timeout.function = tx_credit_callback;
    4.77 -                netif->credit_timeout.cpu      = smp_processor_id();
    4.78 -                add_ac_timer(&netif->credit_timeout);
    4.79 +                add_timer_on(&netif->credit_timeout, smp_processor_id());
    4.80                  break;
    4.81              }
    4.82          }
    4.83 -        netif->remaining_credit -= tx.size;
    4.84 -#endif
    4.85 +        netif->remaining_credit -= txreq.size;
    4.86 +
    4.87 +        /*
    4.88 +         * Why the barrier? It ensures that the frontend sees updated req_cons
    4.89 +         * before we check for more work to schedule.
    4.90 +         */
    4.91 +        netif->tx->req_cons = ++netif->tx_req_cons;
    4.92 +        mb();
    4.93  
    4.94          netif_schedule_work(netif);
    4.95  
     5.1 --- a/tools/python/xen/lowlevel/xu/xu.c	Wed Mar 02 09:33:11 2005 +0000
     5.2 +++ b/tools/python/xen/lowlevel/xu/xu.c	Wed Mar 02 17:53:54 2005 +0000
     5.3 @@ -698,6 +698,13 @@ static PyObject *xu_message_get_payload(
     5.4          C2P(netif_be_destroy_t, netif_handle, Int, Long);
     5.5          C2P(netif_be_destroy_t, status,       Int, Long);
     5.6          return dict;
     5.7 +    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
     5.8 +        C2P(netif_be_creditlimit_t, domid,        Int, Long);
     5.9 +        C2P(netif_be_creditlimit_t, netif_handle, Int, Long);
    5.10 +        C2P(netif_be_creditlimit_t, credit_bytes, Int, Long);
    5.11 +        C2P(netif_be_creditlimit_t, period_usec,  Int, Long);
    5.12 +        C2P(netif_be_creditlimit_t, status,       Int, Long);
    5.13 +        return dict;
    5.14      case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
    5.15          C2P(netif_be_connect_t, domid,          Int, Long);
    5.16          C2P(netif_be_connect_t, netif_handle,   Int, Long);
    5.17 @@ -916,6 +923,12 @@ static PyObject *xu_message_new(PyObject
    5.18          P2C(netif_be_destroy_t, domid,        u32);
    5.19          P2C(netif_be_destroy_t, netif_handle, u32);
    5.20          break;
    5.21 +    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT):
    5.22 +        P2C(netif_be_creditlimit_t, domid,        u32);
    5.23 +        P2C(netif_be_creditlimit_t, netif_handle, u32);
    5.24 +        P2C(netif_be_creditlimit_t, credit_bytes, u32);
    5.25 +        P2C(netif_be_creditlimit_t, period_usec,  u32);
    5.26 +        break;
    5.27      case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
    5.28          P2C(netif_be_connect_t, domid,          u32);
    5.29          P2C(netif_be_connect_t, netif_handle,   u32);
     6.1 --- a/tools/python/xen/xend/XendClient.py	Wed Mar 02 09:33:11 2005 +0000
     6.2 +++ b/tools/python/xen/xend/XendClient.py	Wed Mar 02 17:53:54 2005 +0000
     6.3 @@ -278,6 +278,13 @@ class Xend:
     6.4                               { 'op'     : 'maxmem_set',
     6.5                                 'memory' : memory })
     6.6  
     6.7 +    def xend_domain_vif_limit(self, id, vif, credit, period):
     6.8 +        return self.xendPost(self.domainurl(id),
     6.9 +                            { 'op'      : 'vif_credit_limit',
    6.10 +                              'vif'     : vif,
    6.11 +                              'credit'  : credit,
    6.12 +                              'period'  : period })
    6.13 +
    6.14      def xend_domain_vifs(self, id):
    6.15          return self.xendGet(self.domainurl(id),
    6.16                              { 'op'      : 'vifs' })
     7.1 --- a/tools/python/xen/xend/XendDomain.py	Wed Mar 02 09:33:11 2005 +0000
     7.2 +++ b/tools/python/xen/xend/XendDomain.py	Wed Mar 02 17:53:54 2005 +0000
     7.3 @@ -723,6 +723,15 @@ class XendDomain:
     7.4          dominfo = self.domain_lookup(id)
     7.5          return dominfo.get_device_by_index(type, idx)
     7.6  
     7.7 +    def domain_vif_credit_limit(self, id, vif, credit, period):
     7.8 +        """Limit the vif's transmission rate
     7.9 +        """
    7.10 +        dominfo = self.domain_lookup(id)
    7.11 +        try:
    7.12 +            return dominfo.limit_vif(vif, credit, period)
    7.13 +        except Exception, ex:
    7.14 +            raise XendError(str(ex))
    7.15 +        
    7.16      def domain_vif_ls(self, id):
    7.17          """Get list of virtual network interface (vif) indexes for a domain.
    7.18  
     8.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Mar 02 09:33:11 2005 +0000
     8.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Mar 02 17:53:54 2005 +0000
     8.3 @@ -614,6 +614,18 @@ class XendDomainInfo:
     8.4      def get_device_recreate(self, type, index):
     8.5          return self.get_device_savedinfo(type, index) or self.recreate
     8.6  
     8.7 +    def limit_vif(self, vif, credit, period):
     8.8 +        """Limit the rate of a virtual interface
     8.9 +        @param vif:       vif
    8.10 +        @param credit:    vif credit in bytes
    8.11 +        @param period:    vif period in uSec
    8.12 +        @return: 0 on success
    8.13 +        """
    8.14 +    
    8.15 +        ctrl = xend.netif_create(self.dom, recreate=self.recreate)
    8.16 +        d = ctrl.limitDevice(vif, credit, period)
    8.17 +        return d
    8.18 +    
    8.19      def add_config(self, val):
    8.20          """Add configuration data to a virtual machine.
    8.21  
     9.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Wed Mar 02 09:33:11 2005 +0000
     9.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Wed Mar 02 17:53:54 2005 +0000
     9.3 @@ -164,6 +164,15 @@ class SrvDomain(SrvDir):
     9.4          d = fn(req.args, {'dom': self.dom.id})
     9.5          return d
     9.6  
     9.7 +    def op_vif_credit_limit(self, op, req):
     9.8 +        fn = FormFn(self.xd.domain_vif_credit_limit,
     9.9 +                    [['dom', 'str'],
    9.10 +                     ['vif', 'int'],
    9.11 +                     ['credit', 'int'],
    9.12 +                     ['period', 'int']])
    9.13 +        val = fn(req.args, {'dom': self.dom.id})
    9.14 +        return val
    9.15 +
    9.16      def op_vifs(self, op, req):
    9.17          devs = self.xd.domain_vif_ls(self.dom.id)
    9.18          return [ dev.sxpr() for dev in devs ]
    10.1 --- a/tools/python/xen/xend/server/messages.py	Wed Mar 02 09:33:11 2005 +0000
    10.2 +++ b/tools/python/xen/xend/server/messages.py	Wed Mar 02 17:53:54 2005 +0000
    10.3 @@ -150,6 +150,7 @@ CMSG_NETIF_BE_CREATE                =  0
    10.4  CMSG_NETIF_BE_DESTROY               =  1
    10.5  CMSG_NETIF_BE_CONNECT               =  2
    10.6  CMSG_NETIF_BE_DISCONNECT            =  3
    10.7 +CMSG_NETIF_BE_CREDITLIMIT           =  4
    10.8  CMSG_NETIF_BE_DRIVER_STATUS         = 32
    10.9  
   10.10  NETIF_INTERFACE_STATUS_CLOSED       =  0 #/* Interface doesn't exist.    */
   10.11 @@ -173,6 +174,9 @@ netif_formats = {
   10.12      'netif_be_destroy_t':
   10.13      (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
   10.14  
   10.15 +    'netif_be_creditlimit_t':
   10.16 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREDITLIMIT),
   10.17 +
   10.18      'netif_be_driver_status_t':
   10.19      (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS),
   10.20  
    11.1 --- a/tools/python/xen/xend/server/netif.py	Wed Mar 02 09:33:11 2005 +0000
    11.2 +++ b/tools/python/xen/xend/server/netif.py	Wed Mar 02 17:53:54 2005 +0000
    11.3 @@ -346,7 +346,21 @@ class NetDev(controller.SplitDev):
    11.4          vif = val['netif_handle']
    11.5          self.status = NETIF_INTERFACE_STATUS_CONNECTED
    11.6          self.reportStatus()
    11.7 -
    11.8 +        
    11.9 +    def send_be_creditlimit(self, credit, period):
   11.10 +        msg = packMsg('netif_be_creditlimit_t',
   11.11 +                      { 'domid'          : self.controller.dom,
   11.12 +                        'netif_handle'   : self.vif,
   11.13 +                        'credit_bytes'   : credit,
   11.14 +                        'period_usec'    : period })
   11.15 +        d = defer.Deferred()
   11.16 +        d.addCallback(self.respond_be_creditlimit)
   11.17 +        self.getBackendInterface().writeRequest(msg, response=d)
   11.18 +        
   11.19 +    def respond_be_creditlimit(self, msg):
   11.20 +        val = unpackMsg('netif_be_creditlimit_t', msg)
   11.21 +        return self
   11.22 +        
   11.23      def reportStatus(self, resp=0):
   11.24          msg = packMsg('netif_fe_interface_status_t',
   11.25                        { 'handle' : self.vif,
   11.26 @@ -430,6 +444,15 @@ class NetifController(controller.SplitCo
   11.27              d = dev.attach()
   11.28          return d
   11.29  
   11.30 +    def limitDevice(self, vif, credit, period):        
   11.31 +        if vif not in self.devices:
   11.32 +            raise XendError('device does not exist for credit limit: vif'
   11.33 +                            + str(self.dom) + '.' + str(vif))
   11.34 +        
   11.35 +        dev = self.devices[vif]
   11.36 +        d = dev.send_be_creditlimit(credit, period)
   11.37 +        return d
   11.38 +    
   11.39      def recv_fe_driver_status(self, msg, req):
   11.40          if not req: return
   11.41          print
    12.1 --- a/tools/python/xen/xm/main.py	Wed Mar 02 09:33:11 2005 +0000
    12.2 +++ b/tools/python/xen/xm/main.py	Wed Mar 02 17:53:54 2005 +0000
    12.3 @@ -717,6 +717,23 @@ class ProgLog(Prog):
    12.4  
    12.5  xm.prog(ProgLog)
    12.6  
    12.7 +class ProgVifCreditLimit(Prog):
    12.8 +    group = 'vif'
    12.9 +    name= "vif-limit"
   12.10 +    info = """Limit the transmission rate of a virtual network interface."""
   12.11 +
   12.12 +    def help(self, args):
   12.13 +        print args[0], "DOMAIN VIF CREDIT_IN_BYTES PERIOD_IN_USECS"
   12.14 +        print "\nSet the credit limit of a virtual network interface."
   12.15 +
   12.16 +    def main(self, args):
   12.17 +        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
   12.18 +        dom = args[1]
   12.19 +        v = map(int, args[2:5])
   12.20 +        server.xend_domain_vif_limit(dom, *v)
   12.21 +
   12.22 +xm.prog(ProgVifCreditLimit)
   12.23 +
   12.24  class ProgVifList(Prog):
   12.25      group = 'vif'
   12.26      name  = 'vif-list'
    13.1 --- a/xen/include/public/io/domain_controller.h	Wed Mar 02 09:33:11 2005 +0000
    13.2 +++ b/xen/include/public/io/domain_controller.h	Wed Mar 02 17:53:54 2005 +0000
    13.3 @@ -447,6 +447,7 @@ typedef struct {
    13.4  #define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
    13.5  #define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
    13.6  #define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
    13.7 +#define CMSG_NETIF_BE_CREDITLIMIT 4  /* Limit i/f to a given credit limit. */
    13.8  
    13.9  /* Messages to domain controller. */
   13.10  #define CMSG_NETIF_BE_DRIVER_STATUS 32
   13.11 @@ -511,6 +512,22 @@ typedef struct {
   13.12  } PACKED netif_be_destroy_t; /* 12 bytes */
   13.13  
   13.14  /*
   13.15 + * CMSG_NETIF_BE_CREDITLIMIT:
   13.16 + *  Limit a virtual interface to "credit_bytes" bytes per "period_usec" 
   13.17 + *  microseconds.  
   13.18 + */
   13.19 +typedef struct { 
   13.20 +    /* IN */
   13.21 +    domid_t    domid;          /*  0: Domain attached to new interface.   */
   13.22 +    u16        __pad0;         /*  2 */
   13.23 +    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
   13.24 +    u32        credit_bytes;   /*  8: Vifs credit of bytes per period.    */
   13.25 +    u32        period_usec;    /* 12: Credit replenishment period.        */
   13.26 +    /* OUT */
   13.27 +    u32        status;         /* 16 */
   13.28 +} PACKED netif_be_creditlimit_t; /* 20 bytes */
   13.29 +
   13.30 +/*
   13.31   * CMSG_NETIF_BE_CONNECT:
   13.32   *  When the driver sends a successful response then the interface is fully
   13.33   *  connected. The controller will send a CONNECTED notification to the