xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v2 5/7] libxl/vNUMA: VM config parsing functions
@ 2013-09-13  8:50 Elena Ufimtseva
  2013-09-19 14:09 ` George Dunlap
  2013-09-19 14:29 ` George Dunlap
  0 siblings, 2 replies; 13+ messages in thread
From: Elena Ufimtseva @ 2013-09-13  8:50 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, stefano.stabellini, george.dunlap, dario.faggioli,
	lccycc123, ian.jackson, Elena Ufimtseva, sw

vNUMA VM config parsing functions.
Parses VM vNUMA related config, verifies and
sets default values for errorneous parameters.
If sum of all vnodes memory sizes does not match
memory, it will be adjusted accordingly;

Required configuration options:
- nr_vnodes - number of vNUMA nodes;
- vnumamem - vnodes memory ranges list;
optional:
- vdistance - array of distances;
default values: 10 for same node, 20 for the rest;
- vcpu_to_vnode - maps vcpu to vnode;
should be specified for each node, otherwise default
interleaved initialization used;

Examples:
a)
vnodes = 2
vnumamem = "512m, 512m"
b)
memory = 2048
vcpus = 6
vnodes = 2
vnumamem = "1g, 1g"
vnuma_distance = "10 20, 10 20"
vcpu_to_vnode ="1, 0, 0, 0, 1, 1"

Signed-off-by: Elena Ufimtseva <ufimtseva@gmail.com>

---
Changes since v1:
* defined default initializers for config parameters;
* added domain memory adjustment in case vNUMA nodes
sizes do not match it;

TODO:
* have maxmem parsed as list and in conjunction with
nr_nodes use as domain initial memory and vNUMA nodes
sizes;
* use standard xl list parsing functions;
---
 tools/libxl/xl_cmdimpl.c |  205 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 884f050..1520140 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -540,6 +540,143 @@ vcpp_out:
     return rc;
 }
 
+static void vdistance_default(unsigned int *vdistance, unsigned int nr_vnodes)
+{
+    int i, j;
+    for (i = 0; i < nr_vnodes; i++)
+        for (j = 0; j < nr_vnodes; j++)
+            *(vdistance + j * nr_vnodes + i) = i == j ? 10 : 20;
+}
+
+static void vcputovnode_default(unsigned int *vcpu_to_vnode, unsigned int nr_vnodes, unsigned int max_vcpus)
+{
+    int i;
+    if (vcpu_to_vnode == NULL)
+        return;
+    for(i = 0; i < max_vcpus; i++)
+        vcpu_to_vnode[i] = i % nr_vnodes;
+}
+
+static int vdistance_parse(char *vdistcfg, unsigned int *vdistance, unsigned int nr_vnodes)
+{
+    char *endptr, *toka, *tokb, *saveptra = NULL, *saveptrb = NULL;
+    unsigned int *vdist_tmp = NULL;
+    int rc;
+    int i, j, dist, parsed = 0;	
+    rc = -EINVAL;
+
+    if(vdistance == NULL)
+        return rc;
+    vdist_tmp = (unsigned int *)malloc(nr_vnodes * nr_vnodes * sizeof(*vdistance));
+    if (vdist_tmp == NULL)
+        return rc;
+    i =0; j = 0;
+    for (toka = strtok_r(vdistcfg, ",", &saveptra); toka;
+        toka = strtok_r(NULL, ",", &saveptra)) {
+        if ( i >= nr_vnodes ) 
+            goto vdist_parse_err;
+        for (tokb = strtok_r(toka, " ", &saveptrb); tokb;
+            tokb = strtok_r(NULL, " ", &saveptrb)) {
+            if (j >= nr_vnodes) 
+                goto vdist_parse_err;
+            dist = strtol(tokb, &endptr, 10);
+            if (tokb == endptr)
+                goto vdist_parse_err;
+            *(vdist_tmp + j*nr_vnodes + i) = dist;
+            parsed++;
+            j++;
+        }
+        i++;
+        j = 0;
+    }
+    if (parsed == nr_vnodes * nr_vnodes) {
+        memcpy(vdistance, vdist_tmp, nr_vnodes * nr_vnodes * sizeof(*vdistance));
+        rc = 0;
+    }
+vdist_parse_err:
+    if (vdist_tmp !=NULL ) free(vdist_tmp);
+    return rc;
+}
+
+static int vcputovnode_parse(char *cfg, unsigned int *vmap, unsigned int nr_vnodes, unsigned int nr_vcpus)
+{
+    char *toka, *endptr, *saveptra = NULL;
+    unsigned int *vmap_tmp = NULL, nodemap = 0, smask;
+    
+    int rc = 0;
+    int i;
+    rc = -EINVAL;
+    i = 0;
+    smask = ~(~0 << nr_vnodes);
+    if(vmap == NULL)
+        return rc;
+    vmap_tmp = (unsigned int *)malloc(sizeof(*vmap) * nr_vcpus);
+    memset(vmap_tmp, 0, sizeof(*vmap) * nr_vcpus);
+    for (toka = strtok_r(cfg, " ", &saveptra); toka;
+        toka = strtok_r(NULL, " ", &saveptra)) {
+        if (i >= nr_vcpus) goto vmap_parse_out;
+            vmap_tmp[i] = strtoul(toka, &endptr, 10);
+            nodemap |= (1 << vmap_tmp[i]);
+            if( endptr == toka) 
+                goto vmap_parse_out;
+        i++;
+    }
+    memcpy(vmap, vmap_tmp, sizeof(*vmap) * nr_vcpus);
+    if( ((nodemap & smask) + 1) == (1 << nr_vnodes) )
+        rc = i;
+    else 
+        /* Not all nodes have vcpus, will use default map */
+        rc = -EINVAL;
+vmap_parse_out:
+    if (vmap_tmp != NULL) free(vmap_tmp);
+    return rc;
+}
+
+static int vnumamem_parse(char *vmemsizes, uint64_t *vmemregions, int nr_vnodes)
+{
+    uint64_t memsize;
+    char *endptr, *toka, *saveptr = NULL;
+    int rc;
+    int j;
+    
+    rc = -EINVAL;
+    memsize = j = 0;
+    if(vmemregions == NULL)
+        goto vmem_parse_out;
+    for (toka = strtok_r(vmemsizes, ",", &saveptr); toka;
+        toka = strtok_r(NULL, ",", &saveptr)) {
+        if ( j >= nr_vnodes ) 
+            goto vmem_parse_out;
+        memsize = strtoul(toka, &endptr, 10);
+        if (endptr == toka) 
+            goto vmem_parse_out;
+        switch (*endptr) {
+            case 'G':
+            case 'g':
+                memsize = memsize * 1024 * 1024 * 1024;
+                break;
+            case 'M':
+            case 'm':
+                memsize = memsize * 1024 * 1024;
+                break;
+            case 'K':
+            case 'k':
+                memsize = memsize * 1024 ;
+                break;
+            default:
+                continue;
+                break;
+        }
+        if (memsize > 0) {
+            vmemregions[j] = memsize;
+            j++;
+        }
+    }
+    rc = j;
+vmem_parse_out:   
+    return rc;
+}
+
 static void parse_config_data(const char *config_source,
                               const char *config_data,
                               int config_len,
@@ -871,6 +1008,11 @@ static void parse_config_data(const char *config_source,
     {
         char *cmdline = NULL;
         const char *root = NULL, *extra = "";
+        const char *vnumamemcfg = NULL;
+        int nr_vnuma_regions;
+        long unsigned int vnuma_memparsed = 0;
+        const char *vmapcfg  = NULL;
+        const char *vdistcfg = NULL;
 
         xlu_cfg_replace_string (config, "kernel", &b_info->u.pv.kernel, 0);
 
@@ -889,6 +1031,69 @@ static void parse_config_data(const char *config_source,
             exit(1);
         }
 
+        if (!xlu_cfg_get_long (config, "vnodes", &l, 0)) {
+                b_info->nr_vnodes = l;
+                if(b_info->nr_vnodes != 0 && 
+                  !xlu_cfg_get_string (config, "vnumamem", &vnumamemcfg, 0)) 
+                {
+                    b_info->vnuma_memszs = calloc(b_info->nr_vnodes,
+                                                sizeof(*b_info->vnuma_memszs));
+                    if (b_info->vnuma_memszs == NULL) 
+                        exit(1);
+                    char *buf2 = strdup(vnumamemcfg);
+                    nr_vnuma_regions = vnumamem_parse(buf2, b_info->vnuma_memszs,
+                                                            b_info->nr_vnodes);
+                    if(nr_vnuma_regions != b_info->nr_vnodes ) {
+                        fprintf(stderr, "WARNING: Incorrect vNUMA memory config\n");
+                        if(buf2) free(buf2);
+                        exit(1);
+                    }
+                    for(i = 0; i < b_info->nr_vnodes; i++)
+                        vnuma_memparsed = vnuma_memparsed + (b_info->vnuma_memszs[i] >> 10);
+                    if(vnuma_memparsed != b_info->max_memkb)
+                    /* setting up new memory limit */
+                    {
+                        fprintf(stderr, "WARNING: vNUMA memory is not equal to max_mem, adjusting.\n");
+                        b_info->max_memkb = vnuma_memparsed;
+                        b_info->target_memkb = vnuma_memparsed;
+                    }
+                    if (buf2) free(buf2);
+                    b_info->vdistance = (unsigned int *)calloc(b_info->nr_vnodes * b_info->nr_vnodes, 
+                                                            sizeof(*b_info->vdistance));
+                        if (b_info->vdistance == NULL) 
+                           exit(1);
+
+                    if(!xlu_cfg_get_string(config, "vnuma_distance", &vdistcfg, 0)) {
+                                                buf2 = strdup(vdistcfg);
+                        if(vdistance_parse(buf2, b_info->vdistance, b_info->nr_vnodes) < 0)
+                        {
+                            vdistance_default(b_info->vdistance, b_info->nr_vnodes);
+                        } 
+                        if(buf2) free(buf2);
+                    }
+                    else
+                        vdistance_default(b_info->vdistance, b_info->nr_vnodes);
+                    
+                    b_info->vcpu_to_vnode = (unsigned int *)calloc(b_info->max_vcpus,
+                                                                        sizeof(*b_info->vcpu_to_vnode));
+                    if (b_info->vcpu_to_vnode == NULL) 
+                        exit(1);
+                    if(!xlu_cfg_get_string(config, "vcpu_to_vnode", &vmapcfg, 0))
+                    {
+                        buf2 = strdup(vmapcfg);
+                        if (vcputovnode_parse(buf2, b_info->vcpu_to_vnode,
+                                                b_info->nr_vnodes, b_info->max_vcpus) < 0) {
+                            vcputovnode_default(b_info->vcpu_to_vnode, b_info->nr_vnodes, b_info->max_vcpus);
+                        }
+                        if(buf2) free(buf2);
+                    }
+                    else
+                        vcputovnode_default(b_info->vcpu_to_vnode, b_info->nr_vnodes, b_info->max_vcpus);
+                }
+                else 
+                    b_info->nr_vnodes=0;
+        }
+        
         xlu_cfg_replace_string (config, "bootloader", &b_info->u.pv.bootloader, 0);
         switch (xlu_cfg_get_list_as_string_list(config, "bootloader_args",
                                       &b_info->u.pv.bootloader_args, 1))
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-10-14 16:52 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-13  8:50 [PATCH RFC v2 5/7] libxl/vNUMA: VM config parsing functions Elena Ufimtseva
2013-09-19 14:09 ` George Dunlap
2013-09-19 14:29 ` George Dunlap
2013-10-09 18:45   ` Elena Ufimtseva
2013-10-10  8:38     ` Dario Faggioli
2013-10-10 16:25       ` Elena Ufimtseva
2013-10-10 21:32         ` Dario Faggioli
2013-10-10 22:32           ` Elena Ufimtseva
2013-10-11 11:18           ` Ian Jackson
2013-10-14 13:15             ` Dario Faggioli
2013-10-14 13:26               ` Ian Jackson
2013-10-14 16:52                 ` Elena Ufimtseva
2013-10-14 16:45               ` Elena Ufimtseva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).