aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-31 15:34:52 +0100
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2006-03-31 15:34:52 +0100
commite5829dcbe18cb47ca3c55b589289bbb67dd41213 (patch)
tree562905db133d3e9c87632775287c9e5b46ad4421
parentf8253f9f488a40360cbd57d2d2efbf2ebc0671a3 (diff)
downloadxen-e5829dcbe18cb47ca3c55b589289bbb67dd41213.tar.gz
xen-e5829dcbe18cb47ca3c55b589289bbb67dd41213.tar.bz2
xen-e5829dcbe18cb47ca3c55b589289bbb67dd41213.zip
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>
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/common.h1
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/interface.c19
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c43
-rw-r--r--tools/python/xen/xend/server/netif.py90
-rw-r--r--tools/python/xen/xm/create.py2
5 files changed, 130 insertions, 25 deletions
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h
index ab52a03f07..e328b63e54 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h
@@ -97,7 +97,6 @@ typedef struct netif_st {
#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
-void netif_creditlimit(netif_t *netif);
void netif_disconnect(netif_t *netif);
netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
index 79944d6440..be96a6d3ac 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
@@ -293,25 +293,6 @@ void free_netif(netif_t *netif)
schedule_work(&netif->free_work);
}
-void netif_creditlimit(netif_t *netif)
-{
-#if 0
- /* Set the credit limit (reset remaining credit to new limit). */
- netif->credit_bytes = creditlimit->credit_bytes;
- netif->remaining_credit = creditlimit->credit_bytes;
- netif->credit_usec = creditlimit->period_usec;
-
- if (netif->status == CONNECTED) {
- /*
- * Schedule work so that any packets waiting under previous
- * credit limit are dealt with (acts as a replenishment point).
- */
- netif->credit_timeout.expires = jiffies;
- netif_schedule_work(netif);
- }
-#endif
-}
-
void netif_disconnect(netif_t *netif)
{
switch (netif->status) {
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
index ea9a02e28e..d270f099c4 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
@@ -233,9 +233,44 @@ static void frontend_changed(struct xenbus_device *dev,
static void maybe_connect(struct backend_info *be)
{
- if (be->netif != NULL && be->frontend_state == XenbusStateConnected) {
+ if (be->netif && (be->frontend_state == XenbusStateConnected))
connect(be);
- }
+}
+
+static void xen_net_read_rate(struct xenbus_device *dev,
+ unsigned long *bytes, unsigned long *usec)
+{
+ char *s, *e;
+ unsigned long b, u;
+ char *ratestr;
+
+ /* Default to unlimited bandwidth. */
+ *bytes = ~0UL;
+ *usec = 0;
+
+ ratestr = xenbus_read(XBT_NULL, dev->nodename, "rate", NULL);
+ if (IS_ERR(ratestr))
+ return;
+
+ s = ratestr;
+ b = simple_strtoul(s, &e, 10);
+ if ((s == e) || (*e != ','))
+ goto fail;
+
+ s = e + 1;
+ u = simple_strtoul(s, &e, 10);
+ if ((s == e) || (*e != '\0'))
+ goto fail;
+
+ *bytes = b;
+ *usec = u;
+
+ kfree(ratestr);
+ return;
+
+ fail:
+ WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
+ kfree(ratestr);
}
@@ -254,6 +289,10 @@ static void connect(struct backend_info *be)
return;
}
+ xen_net_read_rate(dev, &be->netif->credit_bytes,
+ &be->netif->credit_usec);
+ be->netif->remaining_credit = be->netif->credit_bytes;
+
xenbus_switch_state(dev, XenbusStateConnected);
}
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index 028bbf3989..94016e3628 100644
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -22,6 +22,7 @@
import os
import random
+import re
from xen.xend import sxp
from xen.xend import XendRoot
@@ -50,6 +51,86 @@ def randomMAC():
random.randint(0x00, 0xff) ]
return ':'.join(map(lambda x: "%02x" % x, mac))
+rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$")
+
+def parseRate(ratestr):
+ """if parsing fails this will return default of unlimited rate"""
+ bytes_per_interval = 0xffffffffL # 0xffffffff # big default
+ interval_usecs = 0L # disabled
+
+ m = rate_re.match(ratestr)
+ if m:
+ bytes_per_sec = long(m.group(1))
+
+ if m.group(2) == 'G':
+ bytes_per_sec *= 1000 * 1000 * 1000
+ elif m.group(2) == 'M':
+ bytes_per_sec *= 1000 * 1000
+ elif m.group(2) == 'K':
+ bytes_per_sec *= 1000
+
+ if m.group(3) == 'b':
+ bytes_per_sec /= 8
+
+ if m.group(5) is None:
+ interval_usecs = 50000L # 50ms default
+ else:
+ interval_usecs = long(m.group(5))
+ if m.group(6) == '':
+ interval_usecs *= 1000 * 1000
+ elif m.group(6) == 'm':
+ interval_usecs *= 1000
+
+ bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L
+
+ # overflow / underflow checking: default to unlimited rate
+ if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \
+ interval_usecs == 0 or interval_usecs > 0xffffffffL:
+ bytes_per_interval = 0xffffffffL
+ interval_usecs = 0L
+
+ return "%lu,%lu" % (bytes_per_interval, interval_usecs)
+
+
+write_rate_G_re = re.compile('^([0-9]+)000000000(B/s@[0-9]+us)$')
+write_rate_M_re = re.compile('^([0-9]+)000000(B/s@[0-9]+us)$')
+write_rate_K_re = re.compile('^([0-9]+)000(B/s@[0-9]+us)$')
+write_rate_s_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000000us$')
+write_rate_m_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000us$')
+
+def formatRate(rate):
+ (bytes_per_interval, interval_usecs) = map(long, rate.split(','))
+
+ if interval_usecs != 0:
+ bytes_per_second = (bytes_per_interval * 1000 * 1000) / interval_usecs
+ else:
+ bytes_per_second = 0xffffffffL
+
+ ratestr = "%uB/s@%uus" % (bytes_per_second, interval_usecs)
+
+ # look for '000's
+ m = write_rate_G_re.match(ratestr)
+ if m:
+ ratestr = m.group(1) + "G" + m.group(2)
+ else:
+ m = write_rate_M_re.match(ratestr)
+ if m:
+ ratestr = m.group(1) + "M" + m.group(2)
+ else:
+ m = write_rate_K_re.match(ratestr)
+ if m:
+ ratestr = m.group(1) + "K" + m.group(2)
+
+ m = write_rate_s_re.match(ratestr)
+ if m:
+ ratestr = m.group(1) + "s"
+ else:
+ m = write_rate_m_re.match(ratestr)
+ if m:
+ ratestr = m.group(1) + "ms"
+
+ return ratestr
+
class NetifController(DevController):
"""Network interface controller. Handles all network devices for a domain.
@@ -75,6 +156,7 @@ class NetifController(DevController):
bridge = sxp.child_value(config, 'bridge')
mac = sxp.child_value(config, 'mac')
vifname = sxp.child_value(config, 'vifname')
+ rate = sxp.child_value(config, 'rate')
ipaddr = _get_config_ipaddr(config)
devid = self.allocateDeviceID()
@@ -98,6 +180,8 @@ class NetifController(DevController):
back['bridge'] = bridge
if vifname:
back['vifname'] = vifname
+ if rate:
+ back['rate'] = parseRate(rate)
return (devid, back, front)
@@ -107,8 +191,8 @@ class NetifController(DevController):
result = DevController.configuration(self, devid)
- (script, ip, bridge, mac, typ, vifname) = self.readBackend(
- devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname')
+ (script, ip, bridge, mac, typ, vifname, rate) = self.readBackend(
+ devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname', 'rate')
if script:
result.append(['script',
@@ -125,5 +209,7 @@ class NetifController(DevController):
result.append(['type', typ])
if vifname:
result.append(['vifname', vifname])
+ if rate:
+ result.append(['rate', formatRate(rate)])
return result
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 2933af5e4f..6da9ed3711 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -552,7 +552,7 @@ def configure_vifs(config_devs, vals):
def f(k):
if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
- 'vifname']:
+ 'vifname', 'rate']:
err('Invalid vif option: ' + k)
config_vif.append([k, d[k]])