diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-10-10 14:12:05 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-10-10 14:12:05 +0000 |
commit | dce8f3f323b33ab04d5b75ff29155d33570ecaa3 (patch) | |
tree | d9e82270eca87039c344d610dc7ab7312d4233ca | |
parent | f5ecfd754290ed8ca28da55530886af4d86aeaef (diff) | |
download | xen-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-- | .rootkeys | 1 | ||||
-rw-r--r-- | tools/internal/Makefile | 2 | ||||
-rw-r--r-- | tools/internal/xi_vif_params.c | 86 | ||||
-rw-r--r-- | tools/misc/xen_read_console.c | 3 | ||||
-rw-r--r-- | xen/common/network.c | 53 | ||||
-rw-r--r-- | xen/include/hypervisor-ifs/network.h | 19 | ||||
-rw-r--r-- | xen/include/xeno/vif.h | 6 | ||||
-rw-r--r-- | xen/net/dev.c | 45 |
8 files changed, 195 insertions, 20 deletions
@@ -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; |