aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-10-10 14:12:05 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-10-10 14:12:05 +0000
commitdce8f3f323b33ab04d5b75ff29155d33570ecaa3 (patch)
treed9e82270eca87039c344d610dc7ab7312d4233ca
parentf5ecfd754290ed8ca28da55530886af4d86aeaef (diff)
downloadxen-dce8f3f323b33ab04d5b75ff29155d33570ecaa3.tar.gz
xen-dce8f3f323b33ab04d5b75ff29155d33570ecaa3.tar.bz2
xen-dce8f3f323b33ab04d5b75ff29155d33570ecaa3.zip
bitkeeper revision 1.500 (3f86be35Q1ywfgRyq1VKkvPUP_JZ_A)
xi_vif_params.c: new file dev.c, vif.h, network.h, network.c, xen_read_console.c, Makefile: Credit-based network scheduling.
-rw-r--r--.rootkeys1
-rw-r--r--tools/internal/Makefile2
-rw-r--r--tools/internal/xi_vif_params.c86
-rw-r--r--tools/misc/xen_read_console.c3
-rw-r--r--xen/common/network.c53
-rw-r--r--xen/include/hypervisor-ifs/network.h19
-rw-r--r--xen/include/xeno/vif.h6
-rw-r--r--xen/net/dev.c45
8 files changed, 195 insertions, 20 deletions
diff --git a/.rootkeys b/.rootkeys
index e212512e4b..de66e17a7d 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -172,6 +172,7 @@
3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c
3eb781fd0Eo9K1jEFCSAVzO51i_ngg tools/internal/xi_stop.c
3f108ae2to5nHRRXfvUK7oxgjcW_yA tools/internal/xi_usage.c
+3f86be322bd0h9jG3krZFOUgCDoxZg tools/internal/xi_vif_params.c
3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
diff --git a/tools/internal/Makefile b/tools/internal/Makefile
index ac76ebbb7c..3fb527fd07 100644
--- a/tools/internal/Makefile
+++ b/tools/internal/Makefile
@@ -9,7 +9,7 @@ OBJS = $(patsubst %.c,%.o,$(SRCS))
TARGETS = xi_create xi_start xi_stop xi_destroy xi_build
TARGETS += xi_phys_grant xi_phys_revoke xi_phys_probe xi_list
-TARGETS += xi_sched_global xi_sched_domain xi_usage
+TARGETS += xi_sched_global xi_sched_domain xi_usage xi_vif_params
INSTALL = $(TARGETS) xi_vifinit xi_helper
all: $(TARGETS)
diff --git a/tools/internal/xi_vif_params.c b/tools/internal/xi_vif_params.c
new file mode 100644
index 0000000000..e954253f04
--- /dev/null
+++ b/tools/internal/xi_vif_params.c
@@ -0,0 +1,86 @@
+
+#include "hypervisor-ifs/dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+static char *argv0 = "internal_domain_vif_params";
+
+int main(int argc, char **argv)
+{
+ network_op_t netop;
+ int domain, vif;
+ unsigned long credit_bytes, credit_usec;
+
+ if ( argv[0] != NULL )
+ argv0 = argv[0];
+
+ if ( (argc != 3) && (argc != 5) )
+ {
+ fprintf(stderr, "Usage: %s <domain-id> <vif-id> "
+ "[<credit-bytes> <credit-usec>]\n", argv0);
+ fprintf(stderr, "Specify <credit usec> == 0 to disable scheduling\n");
+ return 1;
+ }
+
+ domain = atol(argv[1]);
+ vif = atol(argv[2]);
+
+ if ( argc == 5 )
+ {
+ credit_bytes = atol(argv[3]);
+ credit_usec = atol(argv[4]);
+
+ netop.cmd = NETWORK_OP_VIFSETPARAMS;
+ netop.u.vif_setparams.domain = domain;
+ netop.u.vif_setparams.vif = vif;
+ netop.u.vif_setparams.credit_bytes = credit_bytes;
+ netop.u.vif_setparams.credit_usec = credit_usec;
+ if ( do_network_op(&netop) < 0 )
+ return 1;
+
+ if ( credit_usec != 0 )
+ {
+ printf("Set scheduling to %lu bytes every"
+ " %lu usecs (%2.2f Mbps)\n",
+ credit_bytes, credit_usec,
+ ((float)credit_bytes/(1024.0*1024.0/8.0)) /
+ ((float)credit_usec/1000000.0));
+ }
+ else
+ {
+ printf("Disabled rate limiting for vif\n");
+ }
+ }
+ else
+ {
+ netop.cmd = NETWORK_OP_VIFGETINFO;
+ netop.u.vif_getinfo.domain = domain;
+ netop.u.vif_getinfo.vif = vif;
+ if ( do_network_op(&netop) < 0 )
+ return 1;
+
+ printf("%lld bytes transmitted\n"
+ "%lld packets transmitted\n"
+ "%lld bytes received\n"
+ "%lld packets received\n",
+ netop.u.vif_getinfo.total_bytes_sent,
+ netop.u.vif_getinfo.total_packets_sent,
+ netop.u.vif_getinfo.total_bytes_received,
+ netop.u.vif_getinfo.total_packets_received);
+
+ if ( netop.u.vif_getinfo.credit_usec != 0 )
+ {
+ printf("Scheduling: %lu bytes every %lu usecs (%2.2f Mbps)\n",
+ netop.u.vif_getinfo.credit_bytes,
+ netop.u.vif_getinfo.credit_usec,
+ ((float)netop.u.vif_getinfo.credit_bytes/(1024.0*1024.0/8.0)) /
+ ((float)netop.u.vif_getinfo.credit_usec/1000000.0));
+ }
+ else
+ {
+ printf("Scheduling: no rate limit\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/misc/xen_read_console.c b/tools/misc/xen_read_console.c
index 43879e5035..766d24f6f3 100644
--- a/tools/misc/xen_read_console.c
+++ b/tools/misc/xen_read_console.c
@@ -11,7 +11,7 @@
int main(void)
{
- unsigned char buf[208], abuf[32];
+ unsigned char buf[208];
struct sockaddr_in addr, from;
int fromlen = sizeof(from);
int len, fd = socket(PF_INET, SOCK_DGRAM, 0);
@@ -37,6 +37,7 @@ int main(void)
>= 0 )
{
#if 0
+ unsigned char abuf[32];
printf("%d-byte message from %s:%d --\n", len,
inet_ntop(AF_INET, &from.sin_addr, abuf, sizeof(abuf)),
ntohs(from.sin_port));
diff --git a/xen/common/network.c b/xen/common/network.c
index 5a8fd56474..d51195059e 100644
--- a/xen/common/network.c
+++ b/xen/common/network.c
@@ -105,6 +105,10 @@ net_vif_t *create_net_vif(int domain)
spin_lock_init(&new_vif->rx_lock);
spin_lock_init(&new_vif->tx_lock);
+ new_vif->credit_bytes = new_vif->remaining_credit = ~0UL;
+ new_vif->credit_usec = 0UL;
+ init_ac_timer(&new_vif->credit_timeout, 0);
+
if ( (p->domain == 0) && (dom_vif_idx == 0) )
{
/*
@@ -246,35 +250,46 @@ int vif_query(vif_query_t *vq)
*/
int vif_getinfo(vif_getinfo_t *info)
{
- struct task_struct *p;
net_vif_t *vif;
- info->total_bytes_sent =
- info->total_bytes_received =
- info->total_packets_sent =
- info->total_packets_received = -1;
-
- if ( !(p = find_domain_by_id(info->domain)) )
- return -ENOSYS;
-
- vif = p->net_vif_list[info->vif];
-
+ vif = find_vif_by_id((info->domain << VIF_DOMAIN_SHIFT) | info->vif);
if ( vif == NULL )
- {
- put_task_struct(p);
- return -ENOSYS;
- }
+ return -ESRCH;
info->total_bytes_sent = vif->total_bytes_sent;
info->total_bytes_received = vif->total_bytes_received;
info->total_packets_sent = vif->total_packets_sent;
info->total_packets_received = vif->total_packets_received;
- put_task_struct(p);
+ info->credit_bytes = vif->credit_bytes;
+ info->credit_usec = vif->credit_usec;
+
+ put_vif(vif);
return 0;
}
+
+int vif_setparams(vif_setparams_t *params)
+{
+ net_vif_t *vif;
+
+ vif = find_vif_by_id((params->domain << VIF_DOMAIN_SHIFT) | params->vif);
+ if ( vif == NULL )
+ return -ESRCH;
+
+ /* Turning off rate limiting? */
+ if ( params->credit_usec == 0 )
+ params->credit_bytes = ~0UL;
+
+ vif->credit_bytes = vif->remaining_credit = params->credit_bytes;
+ vif->credit_usec = params->credit_usec;
+
+ put_vif(vif);
+
+ return 0;
+}
+
/* ----[ Net Rule Functions ]-----------------------------------------------*/
@@ -572,6 +587,12 @@ long do_network_op(network_op_t *u_network_op)
}
break;
+ case NETWORK_OP_VIFSETPARAMS:
+ {
+ ret = vif_setparams(&op.u.vif_setparams);
+ }
+ break;
+
default:
ret = -ENOSYS;
}
diff --git a/xen/include/hypervisor-ifs/network.h b/xen/include/hypervisor-ifs/network.h
index cd64f4fa73..c35f1bab15 100644
--- a/xen/include/hypervisor-ifs/network.h
+++ b/xen/include/hypervisor-ifs/network.h
@@ -127,13 +127,30 @@ typedef struct vif_getinfo_st
{
unsigned int domain;
unsigned int vif;
+
/* domain & vif are supplied by dom0, the rest are response fields */
long long total_bytes_sent;
long long total_bytes_received;
long long total_packets_sent;
long long total_packets_received;
+
+ /* Current scheduling parameters */
+ unsigned long credit_bytes;
+ unsigned long credit_usec;
} vif_getinfo_t;
+/*
+ * Set parameters associated with a VIF. Currently this is only scheduling
+ * parameters --- permit 'credit_bytes' to be transmitted every 'credit_usec'.
+ */
+typedef struct vif_setparams_st
+{
+ unsigned int domain;
+ unsigned int vif;
+ unsigned long credit_bytes;
+ unsigned long credit_usec;
+} vif_setparams_t;
+
/* Network trap operations and associated structure.
* This presently just handles rule insertion and deletion, but will
* evenually have code to add and remove interfaces.
@@ -144,6 +161,7 @@ typedef struct vif_getinfo_st
#define NETWORK_OP_GETRULELIST 2
#define NETWORK_OP_VIFQUERY 3
#define NETWORK_OP_VIFGETINFO 4
+#define NETWORK_OP_VIFSETPARAMS 5
typedef struct network_op_st
{
@@ -153,6 +171,7 @@ typedef struct network_op_st
net_rule_t net_rule;
vif_query_t vif_query;
vif_getinfo_t vif_getinfo;
+ vif_setparams_t vif_setparams;
}
u;
} network_op_t;
diff --git a/xen/include/xeno/vif.h b/xen/include/xeno/vif.h
index ee9201011a..f3ee9fa616 100644
--- a/xen/include/xeno/vif.h
+++ b/xen/include/xeno/vif.h
@@ -72,6 +72,12 @@ typedef struct net_vif_st {
long long total_packets_sent;
long long total_packets_received;
+ /* Trasnmit shaping: allow 'credit_bytes' everu 'credit_usec'. */
+ unsigned long credit_bytes;
+ unsigned long credit_usec;
+ unsigned long remaining_credit;
+ struct ac_timer credit_timeout;
+
/* Miscellaneous private stuff. */
struct task_struct *domain;
unsigned int idx; /* index within domain */
diff --git a/xen/net/dev.c b/xen/net/dev.c
index 22b81bcc58..2fcf935319 100644
--- a/xen/net/dev.c
+++ b/xen/net/dev.c
@@ -1824,6 +1824,18 @@ inline int init_tx_header(net_vif_t *vif, u8 *data,
return proto;
}
+static void tx_credit_callback(unsigned long data)
+{
+ net_vif_t *vif = (net_vif_t *)data;
+
+ vif->remaining_credit = vif->credit_bytes;
+
+ if ( get_tx_bufs(vif) )
+ {
+ add_to_net_schedule_list_tail(vif);
+ maybe_schedule_tx_action();
+ }
+}
static int get_tx_bufs(net_vif_t *vif)
{
@@ -1837,7 +1849,7 @@ static int get_tx_bufs(net_vif_t *vif)
unsigned short protocol;
struct sk_buff *skb;
tx_req_entry_t tx;
- int i, j, ret;
+ int i, j, ret = 0;
unsigned long flags;
if ( vif->tx_req_cons == shared_idxs->tx_req_prod )
@@ -1845,6 +1857,10 @@ static int get_tx_bufs(net_vif_t *vif)
spin_lock_irqsave(&vif->tx_lock, flags);
+ /* Currently waiting for more credit? */
+ if ( vif->remaining_credit == 0 )
+ goto out;
+
j = vif->tx_prod;
/*
@@ -1868,6 +1884,29 @@ static int get_tx_bufs(net_vif_t *vif)
continue;
}
+ /* Credit-based scheduling. */
+ if ( tx.size > vif->remaining_credit )
+ {
+ s_time_t now = NOW(), next_credit =
+ vif->credit_timeout.expires + MICROSECS(vif->credit_usec);
+ if ( next_credit <= now )
+ {
+ vif->credit_timeout.expires = now;
+ vif->remaining_credit = vif->credit_bytes;
+ }
+ else
+ {
+ vif->remaining_credit = 0;
+ vif->credit_timeout.expires = next_credit;
+ vif->credit_timeout.data = (unsigned long)vif;
+ vif->credit_timeout.function = tx_credit_callback;
+ vif->credit_timeout.cpu = smp_processor_id();
+ add_ac_timer(&vif->credit_timeout);
+ break;
+ }
+ }
+ vif->remaining_credit -= tx.size;
+
/* No crossing a page boundary as the payload mustn't fragment. */
if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE )
{
@@ -1966,12 +2005,14 @@ static int get_tx_bufs(net_vif_t *vif)
*/
smp_mb();
- if ( (vif->tx_req_cons = i) != shared_idxs->tx_req_prod )
+ if ( ((vif->tx_req_cons = i) != shared_idxs->tx_req_prod) &&
+ (vif->remaining_credit != 0) )
goto again;
if ( (ret = (vif->tx_prod != j)) )
vif->tx_prod = j;
+ out:
spin_unlock_irqrestore(&vif->tx_lock, flags);
return ret;