ia64/xen-unstable

changeset 9554:dadadf9aeee7

Plumb network vif credit-based rate limiting thorugh xenbus
and xend into xm guest config files.

A new vif parameter 'rate' is supported, with an optional time window
paremeter for specifying granularity of credit replenishment. The default
window is 50ms. For example:

'rate=10Mb/s' 'rate=250KB/s' 'rate=1MB/s@20ms'

From: Chris Clark <christopher.w.clark@gmail.com>

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Mar 31 15:34:52 2006 +0100 (2006-03-31)
parents 2769a38f0e3e
children d76a7a40f3a9
files linux-2.6-xen-sparse/drivers/xen/netback/common.h linux-2.6-xen-sparse/drivers/xen/netback/interface.c linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c tools/python/xen/xend/server/netif.py tools/python/xen/xm/create.py
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Fri Mar 31 13:51:19 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Fri Mar 31 15:34:52 2006 +0100
     1.3 @@ -97,7 +97,6 @@ typedef struct netif_st {
     1.4  #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
     1.5  #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
     1.6  
     1.7 -void netif_creditlimit(netif_t *netif);
     1.8  void netif_disconnect(netif_t *netif);
     1.9  
    1.10  netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Fri Mar 31 13:51:19 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Fri Mar 31 15:34:52 2006 +0100
     2.3 @@ -293,25 +293,6 @@ void free_netif(netif_t *netif)
     2.4  	schedule_work(&netif->free_work);
     2.5  }
     2.6  
     2.7 -void netif_creditlimit(netif_t *netif)
     2.8 -{
     2.9 -#if 0
    2.10 -	/* Set the credit limit (reset remaining credit to new limit). */
    2.11 -	netif->credit_bytes     = creditlimit->credit_bytes;
    2.12 -	netif->remaining_credit = creditlimit->credit_bytes;
    2.13 -	netif->credit_usec      = creditlimit->period_usec;
    2.14 -
    2.15 -	if (netif->status == CONNECTED) {
    2.16 -		/*
    2.17 -		 * Schedule work so that any packets waiting under previous
    2.18 -		 * credit limit are dealt with (acts as a replenishment point).
    2.19 -		 */
    2.20 -		netif->credit_timeout.expires = jiffies;
    2.21 -		netif_schedule_work(netif);
    2.22 -	}
    2.23 -#endif
    2.24 -}
    2.25 -
    2.26  void netif_disconnect(netif_t *netif)
    2.27  {
    2.28  	switch (netif->status) {
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Mar 31 13:51:19 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Fri Mar 31 15:34:52 2006 +0100
     3.3 @@ -233,9 +233,44 @@ static void frontend_changed(struct xenb
     3.4  
     3.5  static void maybe_connect(struct backend_info *be)
     3.6  {
     3.7 -	if (be->netif != NULL && be->frontend_state == XenbusStateConnected) {
     3.8 +	if (be->netif && (be->frontend_state == XenbusStateConnected))
     3.9  		connect(be);
    3.10 -	}
    3.11 +}
    3.12 +
    3.13 +static void xen_net_read_rate(struct xenbus_device *dev,
    3.14 +			      unsigned long *bytes, unsigned long *usec)
    3.15 +{
    3.16 +	char *s, *e;
    3.17 +	unsigned long b, u;
    3.18 +	char *ratestr;
    3.19 +
    3.20 +	/* Default to unlimited bandwidth. */
    3.21 +	*bytes = ~0UL;
    3.22 +	*usec = 0;
    3.23 +
    3.24 +	ratestr = xenbus_read(XBT_NULL, dev->nodename, "rate", NULL);
    3.25 +	if (IS_ERR(ratestr))
    3.26 +		return;
    3.27 +
    3.28 +	s = ratestr;
    3.29 +	b = simple_strtoul(s, &e, 10);
    3.30 +	if ((s == e) || (*e != ','))
    3.31 +		goto fail;
    3.32 +
    3.33 +	s = e + 1;
    3.34 +	u = simple_strtoul(s, &e, 10);
    3.35 +	if ((s == e) || (*e != '\0'))
    3.36 +		goto fail;
    3.37 +
    3.38 +	*bytes = b;
    3.39 +	*usec = u;
    3.40 +
    3.41 +	kfree(ratestr);
    3.42 +	return;
    3.43 +
    3.44 + fail:
    3.45 +	WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
    3.46 +	kfree(ratestr);
    3.47  }
    3.48  
    3.49  
    3.50 @@ -254,6 +289,10 @@ static void connect(struct backend_info 
    3.51  		return;
    3.52  	}
    3.53  
    3.54 +	xen_net_read_rate(dev, &be->netif->credit_bytes,
    3.55 +			  &be->netif->credit_usec);
    3.56 +	be->netif->remaining_credit = be->netif->credit_bytes;
    3.57 +
    3.58  	xenbus_switch_state(dev, XenbusStateConnected);
    3.59  }
    3.60  
     4.1 --- a/tools/python/xen/xend/server/netif.py	Fri Mar 31 13:51:19 2006 +0100
     4.2 +++ b/tools/python/xen/xend/server/netif.py	Fri Mar 31 15:34:52 2006 +0100
     4.3 @@ -22,6 +22,7 @@
     4.4  
     4.5  import os
     4.6  import random
     4.7 +import re
     4.8  
     4.9  from xen.xend import sxp
    4.10  from xen.xend import XendRoot
    4.11 @@ -50,6 +51,86 @@ def randomMAC():
    4.12              random.randint(0x00, 0xff) ]
    4.13      return ':'.join(map(lambda x: "%02x" % x, mac))
    4.14  
    4.15 +rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$")
    4.16 +
    4.17 +def parseRate(ratestr):
    4.18 +    """if parsing fails this will return default of unlimited rate"""
    4.19 +    bytes_per_interval = 0xffffffffL # 0xffffffff # big default
    4.20 +    interval_usecs     = 0L          # disabled
    4.21 +
    4.22 +    m = rate_re.match(ratestr)
    4.23 +    if m:
    4.24 +        bytes_per_sec = long(m.group(1))
    4.25 +
    4.26 +        if m.group(2) == 'G':
    4.27 +            bytes_per_sec *= 1000 * 1000 * 1000
    4.28 +        elif m.group(2) == 'M':
    4.29 +            bytes_per_sec *= 1000 * 1000
    4.30 +        elif m.group(2) == 'K':
    4.31 +            bytes_per_sec *= 1000
    4.32 +
    4.33 +        if m.group(3) == 'b':
    4.34 +            bytes_per_sec /= 8
    4.35 +
    4.36 +        if m.group(5) is None:
    4.37 +            interval_usecs = 50000L      # 50ms default
    4.38 +        else:
    4.39 +            interval_usecs = long(m.group(5))
    4.40 +            if m.group(6) == '':
    4.41 +                interval_usecs *= 1000 * 1000
    4.42 +            elif m.group(6) == 'm':
    4.43 +                interval_usecs *= 1000
    4.44 +
    4.45 +        bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L
    4.46 +
    4.47 +        # overflow / underflow checking: default to unlimited rate
    4.48 +        if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \
    4.49 +           interval_usecs == 0 or interval_usecs > 0xffffffffL:
    4.50 +            bytes_per_interval = 0xffffffffL
    4.51 +            interval_usecs     = 0L
    4.52 +
    4.53 +    return "%lu,%lu" % (bytes_per_interval, interval_usecs)
    4.54 +
    4.55 +
    4.56 +write_rate_G_re = re.compile('^([0-9]+)000000000(B/s@[0-9]+us)$')
    4.57 +write_rate_M_re = re.compile('^([0-9]+)000000(B/s@[0-9]+us)$')
    4.58 +write_rate_K_re = re.compile('^([0-9]+)000(B/s@[0-9]+us)$')
    4.59 +write_rate_s_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000000us$')
    4.60 +write_rate_m_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000us$')
    4.61 +
    4.62 +def formatRate(rate):
    4.63 +    (bytes_per_interval, interval_usecs) = map(long, rate.split(','))
    4.64 +
    4.65 +    if interval_usecs != 0:
    4.66 +        bytes_per_second = (bytes_per_interval * 1000 * 1000) / interval_usecs
    4.67 +    else:
    4.68 +        bytes_per_second = 0xffffffffL
    4.69 +
    4.70 +    ratestr = "%uB/s@%uus" % (bytes_per_second, interval_usecs)
    4.71 +
    4.72 +    # look for '000's
    4.73 +    m = write_rate_G_re.match(ratestr)
    4.74 +    if m:
    4.75 +        ratestr = m.group(1) + "G" + m.group(2)
    4.76 +    else:
    4.77 +        m = write_rate_M_re.match(ratestr)
    4.78 +        if m:
    4.79 +            ratestr = m.group(1) + "M" + m.group(2)
    4.80 +        else:
    4.81 +            m = write_rate_K_re.match(ratestr)
    4.82 +            if m:
    4.83 +                ratestr = m.group(1) + "K" + m.group(2)
    4.84 +
    4.85 +    m = write_rate_s_re.match(ratestr)
    4.86 +    if m:
    4.87 +        ratestr = m.group(1) + "s"
    4.88 +    else:
    4.89 +        m = write_rate_m_re.match(ratestr)
    4.90 +        if m:
    4.91 +            ratestr = m.group(1) + "ms"
    4.92 +
    4.93 +    return ratestr
    4.94 +
    4.95  
    4.96  class NetifController(DevController):
    4.97      """Network interface controller. Handles all network devices for a domain.
    4.98 @@ -75,6 +156,7 @@ class NetifController(DevController):
    4.99          bridge  = sxp.child_value(config, 'bridge')
   4.100          mac     = sxp.child_value(config, 'mac')
   4.101          vifname = sxp.child_value(config, 'vifname')
   4.102 +        rate    = sxp.child_value(config, 'rate')
   4.103          ipaddr  = _get_config_ipaddr(config)
   4.104  
   4.105          devid = self.allocateDeviceID()
   4.106 @@ -98,6 +180,8 @@ class NetifController(DevController):
   4.107              back['bridge'] = bridge
   4.108          if vifname:
   4.109              back['vifname'] = vifname
   4.110 +        if rate:
   4.111 +            back['rate'] = parseRate(rate)
   4.112  
   4.113          return (devid, back, front)
   4.114  
   4.115 @@ -107,8 +191,8 @@ class NetifController(DevController):
   4.116  
   4.117          result = DevController.configuration(self, devid)
   4.118  
   4.119 -        (script, ip, bridge, mac, typ, vifname) = self.readBackend(
   4.120 -            devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname')
   4.121 +        (script, ip, bridge, mac, typ, vifname, rate) = self.readBackend(
   4.122 +            devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname', 'rate')
   4.123  
   4.124          if script:
   4.125              result.append(['script',
   4.126 @@ -125,5 +209,7 @@ class NetifController(DevController):
   4.127              result.append(['type', typ])
   4.128          if vifname:
   4.129              result.append(['vifname', vifname])
   4.130 +        if rate:
   4.131 +            result.append(['rate', formatRate(rate)])
   4.132  
   4.133          return result
     5.1 --- a/tools/python/xen/xm/create.py	Fri Mar 31 13:51:19 2006 +0100
     5.2 +++ b/tools/python/xen/xm/create.py	Fri Mar 31 15:34:52 2006 +0100
     5.3 @@ -552,7 +552,7 @@ def configure_vifs(config_devs, vals):
     5.4  
     5.5          def f(k):
     5.6              if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
     5.7 -                         'vifname']:
     5.8 +                         'vifname', 'rate']:
     5.9                  err('Invalid vif option: ' + k)
    5.10  
    5.11              config_vif.append([k, d[k]])