# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID dadadf9aeee713bbe2f8dc040a74f7cea2223f41
# Parent 2769a38f0e3e7ab544293833276a5d8cd0875483
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@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 2769a38f0e3e -r dadadf9aeee7
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Mar 31 12:51:19 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Mar 31 14:34:52 2006
@@ -97,7 +97,6 @@
#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 -r 2769a38f0e3e -r dadadf9aeee7
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Mar 31
12:51:19 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Mar 31
14:34:52 2006
@@ -291,25 +291,6 @@
{
INIT_WORK(&netif->free_work, free_netif_callback, (void *)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)
diff -r 2769a38f0e3e -r dadadf9aeee7
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Mar 31 12:51:19 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Mar 31 14:34:52 2006
@@ -233,9 +233,44 @@
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);
}
@@ -253,6 +288,10 @@
xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
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 -r 2769a38f0e3e -r dadadf9aeee7 tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py Fri Mar 31 12:51:19 2006
+++ b/tools/python/xen/xend/server/netif.py Fri Mar 31 14:34:52 2006
@@ -22,6 +22,7 @@
import os
import random
+import re
from xen.xend import sxp
from xen.xend import XendRoot
@@ -50,6 +51,86 @@
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 @@
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 @@
back['bridge'] = bridge
if vifname:
back['vifname'] = vifname
+ if rate:
+ back['rate'] = parseRate(rate)
return (devid, back, front)
@@ -107,8 +191,8 @@
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 @@
result.append(['type', typ])
if vifname:
result.append(['vifname', vifname])
+ if rate:
+ result.append(['rate', formatRate(rate)])
return result
diff -r 2769a38f0e3e -r dadadf9aeee7 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Fri Mar 31 12:51:19 2006
+++ b/tools/python/xen/xm/create.py Fri Mar 31 14:34:52 2006
@@ -552,7 +552,7 @@
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]])
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|