1 /*
2  * Copyright 2009-2017 Citrix Ltd and other contributors
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; version 2.1 only. with the special
7  * exception on linking described in file LICENSE.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14 
15 #include <inttypes.h>
16 #include <stdlib.h>
17 
18 #include <libxl.h>
19 #include <libxl_utils.h>
20 #include <libxlutil.h>
21 
22 #include "xl.h"
23 #include "xl_utils.h"
24 #include "xl_parse.h"
25 
sched_domain_get(libxl_scheduler sched,int domid,libxl_domain_sched_params * scinfo)26 static int sched_domain_get(libxl_scheduler sched, int domid,
27                             libxl_domain_sched_params *scinfo)
28 {
29     if (libxl_domain_sched_params_get(ctx, domid, scinfo)) {
30         fprintf(stderr, "libxl_domain_sched_params_get failed.\n");
31         return 1;
32     }
33     if (scinfo->sched != sched) {
34         fprintf(stderr, "libxl_domain_sched_params_get returned %s not %s.\n",
35                 libxl_scheduler_to_string(scinfo->sched),
36                 libxl_scheduler_to_string(sched));
37         return 1;
38     }
39 
40     return 0;
41 }
42 
sched_domain_set(int domid,const libxl_domain_sched_params * scinfo)43 static int sched_domain_set(int domid, const libxl_domain_sched_params *scinfo)
44 {
45     if (libxl_domain_sched_params_set(ctx, domid, scinfo)) {
46         fprintf(stderr, "libxl_domain_sched_params_set failed.\n");
47         return 1;
48     }
49 
50     return 0;
51 }
52 
sched_vcpu_get(libxl_scheduler sched,int domid,libxl_vcpu_sched_params * scinfo)53 static int sched_vcpu_get(libxl_scheduler sched, int domid,
54                           libxl_vcpu_sched_params *scinfo)
55 {
56     int rc;
57 
58     rc = libxl_vcpu_sched_params_get(ctx, domid, scinfo);
59     if (rc) {
60         fprintf(stderr, "libxl_vcpu_sched_params_get failed.\n");
61         exit(EXIT_FAILURE);
62     }
63     if (scinfo->sched != sched) {
64         fprintf(stderr, "libxl_vcpu_sched_params_get returned %s not %s.\n",
65                 libxl_scheduler_to_string(scinfo->sched),
66                 libxl_scheduler_to_string(sched));
67         return 1;
68     }
69 
70     return 0;
71 }
72 
sched_vcpu_get_all(libxl_scheduler sched,int domid,libxl_vcpu_sched_params * scinfo)73 static int sched_vcpu_get_all(libxl_scheduler sched, int domid,
74                               libxl_vcpu_sched_params *scinfo)
75 {
76     int rc;
77 
78     rc = libxl_vcpu_sched_params_get_all(ctx, domid, scinfo);
79     if (rc) {
80         fprintf(stderr, "libxl_vcpu_sched_params_get_all failed.\n");
81         exit(EXIT_FAILURE);
82     }
83     if (scinfo->sched != sched) {
84         fprintf(stderr, "libxl_vcpu_sched_params_get_all returned %s not %s.\n",
85                 libxl_scheduler_to_string(scinfo->sched),
86                 libxl_scheduler_to_string(sched));
87         return 1;
88     }
89 
90     return 0;
91 }
92 
sched_vcpu_set(int domid,const libxl_vcpu_sched_params * scinfo)93 static int sched_vcpu_set(int domid, const libxl_vcpu_sched_params *scinfo)
94 {
95     int rc;
96 
97     rc = libxl_vcpu_sched_params_set(ctx, domid, scinfo);
98     if (rc) {
99         fprintf(stderr, "libxl_vcpu_sched_params_set failed.\n");
100         exit(EXIT_FAILURE);
101     }
102 
103     return 0;
104 }
105 
sched_vcpu_set_all(int domid,const libxl_vcpu_sched_params * scinfo)106 static int sched_vcpu_set_all(int domid, const libxl_vcpu_sched_params *scinfo)
107 {
108     int rc;
109 
110     rc = libxl_vcpu_sched_params_set_all(ctx, domid, scinfo);
111     if (rc) {
112         fprintf(stderr, "libxl_vcpu_sched_params_set_all failed.\n");
113         exit(EXIT_FAILURE);
114     }
115 
116     return 0;
117 }
118 
sched_credit_params_set(int poolid,libxl_sched_credit_params * scinfo)119 static int sched_credit_params_set(int poolid, libxl_sched_credit_params *scinfo)
120 {
121     if (libxl_sched_credit_params_set(ctx, poolid, scinfo)) {
122         fprintf(stderr, "libxl_sched_credit_params_set failed.\n");
123         return 1;
124     }
125 
126     return 0;
127 }
128 
sched_credit_params_get(int poolid,libxl_sched_credit_params * scinfo)129 static int sched_credit_params_get(int poolid, libxl_sched_credit_params *scinfo)
130 {
131     if (libxl_sched_credit_params_get(ctx, poolid, scinfo)) {
132         fprintf(stderr, "libxl_sched_credit_params_get failed.\n");
133         return 1;
134     }
135 
136     return 0;
137 }
138 
sched_credit_domain_output(int domid)139 static int sched_credit_domain_output(int domid)
140 {
141     char *domname;
142     libxl_domain_sched_params scinfo;
143 
144     if (domid < 0) {
145         printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
146         return 0;
147     }
148 
149     libxl_domain_sched_params_init(&scinfo);
150     if (sched_domain_get(LIBXL_SCHEDULER_CREDIT, domid, &scinfo)) {
151         libxl_domain_sched_params_dispose(&scinfo);
152         return 1;
153     }
154     domname = libxl_domid_to_name(ctx, domid);
155     printf("%-33s %4d %6d %4d\n",
156         domname,
157         domid,
158         scinfo.weight,
159         scinfo.cap);
160     free(domname);
161     libxl_domain_sched_params_dispose(&scinfo);
162     return 0;
163 }
164 
sched_credit_pool_output(uint32_t poolid)165 static int sched_credit_pool_output(uint32_t poolid)
166 {
167     libxl_sched_credit_params scparam;
168     char *poolname;
169 
170     poolname = libxl_cpupoolid_to_name(ctx, poolid);
171     if (sched_credit_params_get(poolid, &scparam)) {
172         printf("Cpupool %s: [sched params unavailable]\n",
173                poolname);
174     } else {
175         printf("Cpupool %s: tslice=%dms ratelimit=%dus\n",
176                poolname,
177                scparam.tslice_ms,
178                scparam.ratelimit_us);
179     }
180     free(poolname);
181     return 0;
182 }
183 
sched_credit2_params_set(int poolid,libxl_sched_credit2_params * scinfo)184 static int sched_credit2_params_set(int poolid,
185                                     libxl_sched_credit2_params *scinfo)
186 {
187     if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
188         fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
189         return 1;
190     }
191 
192     return 0;
193 }
194 
sched_credit2_params_get(int poolid,libxl_sched_credit2_params * scinfo)195 static int sched_credit2_params_get(int poolid,
196                                     libxl_sched_credit2_params *scinfo)
197 {
198     if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
199         fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
200         return 1;
201     }
202 
203     return 0;
204 }
205 
sched_credit2_domain_output(int domid)206 static int sched_credit2_domain_output(int domid)
207 {
208     char *domname;
209     libxl_domain_sched_params scinfo;
210 
211     if (domid < 0) {
212         printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
213         return 0;
214     }
215 
216     libxl_domain_sched_params_init(&scinfo);
217     if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
218         libxl_domain_sched_params_dispose(&scinfo);
219         return 1;
220     }
221     domname = libxl_domid_to_name(ctx, domid);
222     printf("%-33s %4d %6d %4d\n",
223         domname,
224         domid,
225         scinfo.weight,
226         scinfo.cap);
227     free(domname);
228     libxl_domain_sched_params_dispose(&scinfo);
229     return 0;
230 }
231 
sched_credit2_pool_output(uint32_t poolid)232 static int sched_credit2_pool_output(uint32_t poolid)
233 {
234     libxl_sched_credit2_params scparam;
235     char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
236 
237     if (sched_credit2_params_get(poolid, &scparam))
238         printf("Cpupool %s: [sched params unavailable]\n", poolname);
239     else
240         printf("Cpupool %s: ratelimit=%dus\n",
241                poolname, scparam.ratelimit_us);
242 
243     free(poolname);
244 
245     return 0;
246 }
247 
sched_rtds_domain_output(int domid)248 static int sched_rtds_domain_output(
249     int domid)
250 {
251     char *domname;
252     libxl_domain_sched_params scinfo;
253 
254     if (domid < 0) {
255         printf("%-33s %4s %9s %9s %10s\n", "Name", "ID", "Period", "Budget", "Extratime");
256         return 0;
257     }
258 
259     libxl_domain_sched_params_init(&scinfo);
260     if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
261         libxl_domain_sched_params_dispose(&scinfo);
262         return 1;
263     }
264 
265     domname = libxl_domid_to_name(ctx, domid);
266     printf("%-33s %4d %9d %9d %10s\n",
267         domname,
268         domid,
269         scinfo.period,
270         scinfo.budget,
271         scinfo.extratime ? "yes" : "no");
272     free(domname);
273     libxl_domain_sched_params_dispose(&scinfo);
274     return 0;
275 }
276 
sched_rtds_vcpu_output(int domid,libxl_vcpu_sched_params * scinfo)277 static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
278 {
279     char *domname;
280     int rc = 0;
281     int i;
282 
283     if (domid < 0) {
284         printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
285                "VCPU", "Period", "Budget", "Extratime");
286         return 0;
287     }
288 
289     rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
290     if (rc)
291         return 1;
292 
293     domname = libxl_domid_to_name(ctx, domid);
294     for ( i = 0; i < scinfo->num_vcpus; i++ ) {
295         printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
296                domname,
297                domid,
298                scinfo->vcpus[i].vcpuid,
299                scinfo->vcpus[i].period,
300                scinfo->vcpus[i].budget,
301                scinfo->vcpus[i].extratime ? "yes" : "no");
302     }
303     free(domname);
304     return 0;
305 }
306 
sched_rtds_vcpu_output_all(int domid,libxl_vcpu_sched_params * scinfo)307 static int sched_rtds_vcpu_output_all(int domid,
308                                       libxl_vcpu_sched_params *scinfo)
309 {
310     char *domname;
311     int rc = 0;
312     int i;
313 
314     if (domid < 0) {
315         printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
316                "VCPU", "Period", "Budget", "Extratime");
317         return 0;
318     }
319 
320     scinfo->num_vcpus = 0;
321     rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
322     if (rc)
323         return 1;
324 
325     domname = libxl_domid_to_name(ctx, domid);
326     for ( i = 0; i < scinfo->num_vcpus; i++ ) {
327         printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
328                domname,
329                domid,
330                scinfo->vcpus[i].vcpuid,
331                scinfo->vcpus[i].period,
332                scinfo->vcpus[i].budget,
333                scinfo->vcpus[i].extratime ? "yes" : "no");
334     }
335     free(domname);
336     return 0;
337 }
338 
sched_rtds_pool_output(uint32_t poolid)339 static int sched_rtds_pool_output(uint32_t poolid)
340 {
341     char *poolname;
342 
343     poolname = libxl_cpupoolid_to_name(ctx, poolid);
344     printf("Cpupool %s: sched=RTDS\n", poolname);
345 
346     free(poolname);
347     return 0;
348 }
349 
sched_domain_output(libxl_scheduler sched,int (* output)(int),int (* pooloutput)(uint32_t),const char * cpupool)350 static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
351                                int (*pooloutput)(uint32_t), const char *cpupool)
352 {
353     libxl_dominfo *info;
354     libxl_cpupoolinfo *poolinfo = NULL;
355     uint32_t poolid;
356     int nb_domain, n_pools = 0, i, p;
357     int rc = 0;
358 
359     if (cpupool) {
360         if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
361             !libxl_cpupoolid_is_valid(ctx, poolid)) {
362             fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
363             return 1;
364         }
365     }
366 
367     info = libxl_list_domain(ctx, &nb_domain);
368     if (!info) {
369         fprintf(stderr, "libxl_list_domain failed.\n");
370         return 1;
371     }
372     poolinfo = libxl_list_cpupool(ctx, &n_pools);
373     if (!poolinfo) {
374         fprintf(stderr, "error getting cpupool info\n");
375         libxl_dominfo_list_free(info, nb_domain);
376         return 1;
377     }
378 
379     for (p = 0; !rc && (p < n_pools); p++) {
380         if ((poolinfo[p].sched != sched) ||
381             (cpupool && (poolid != poolinfo[p].poolid)))
382             continue;
383 
384         pooloutput(poolinfo[p].poolid);
385 
386         output(-1);
387         for (i = 0; i < nb_domain; i++) {
388             if (info[i].cpupool != poolinfo[p].poolid)
389                 continue;
390             rc = output(info[i].domid);
391             if (rc)
392                 break;
393         }
394     }
395 
396     libxl_cpupoolinfo_list_free(poolinfo, n_pools);
397     libxl_dominfo_list_free(info, nb_domain);
398     return 0;
399 }
400 
sched_vcpu_output(libxl_scheduler sched,int (* output)(int,libxl_vcpu_sched_params *),int (* pooloutput)(uint32_t),const char * cpupool)401 static int sched_vcpu_output(libxl_scheduler sched,
402                              int (*output)(int, libxl_vcpu_sched_params *),
403                              int (*pooloutput)(uint32_t), const char *cpupool)
404 {
405     libxl_dominfo *info;
406     libxl_cpupoolinfo *poolinfo = NULL;
407     uint32_t poolid;
408     int nb_domain, n_pools = 0, i, p;
409     int rc = 0;
410 
411     if (cpupool) {
412         if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
413             || !libxl_cpupoolid_is_valid(ctx, poolid)) {
414             fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
415             return 1;
416         }
417     }
418 
419     info = libxl_list_domain(ctx, &nb_domain);
420     if (!info) {
421         fprintf(stderr, "libxl_list_domain failed.\n");
422         return 1;
423     }
424     poolinfo = libxl_list_cpupool(ctx, &n_pools);
425     if (!poolinfo) {
426         fprintf(stderr, "error getting cpupool info\n");
427         libxl_dominfo_list_free(info, nb_domain);
428         return 1;
429     }
430 
431     for (p = 0; !rc && (p < n_pools); p++) {
432         if ((poolinfo[p].sched != sched) ||
433             (cpupool && (poolid != poolinfo[p].poolid)))
434             continue;
435 
436         pooloutput(poolinfo[p].poolid);
437 
438         output(-1, NULL);
439         for (i = 0; i < nb_domain; i++) {
440             libxl_vcpu_sched_params scinfo;
441             if (info[i].cpupool != poolinfo[p].poolid)
442                 continue;
443             libxl_vcpu_sched_params_init(&scinfo);
444             rc = output(info[i].domid, &scinfo);
445             libxl_vcpu_sched_params_dispose(&scinfo);
446             if (rc)
447                 break;
448         }
449     }
450 
451     libxl_cpupoolinfo_list_free(poolinfo, n_pools);
452     libxl_dominfo_list_free(info, nb_domain);
453     return 0;
454 }
455 
456 /*
457  * <nothing>             : List all domain params and sched params from all pools
458  * -d [domid]            : List domain params for domain
459  * -d [domid] [params]   : Set domain params for domain
460  * -p [pool]             : list all domains and sched params for pool
461  * -s                    : List sched params for poolid 0
462  * -s [params]           : Set sched params for poolid 0
463  * -p [pool] -s          : List sched params for pool
464  * -p [pool] -s [params] : Set sched params for pool
465  * -p [pool] -d...       : Illegal
466  */
main_sched_credit(int argc,char ** argv)467 int main_sched_credit(int argc, char **argv)
468 {
469     const char *dom = NULL;
470     const char *cpupool = NULL;
471     int weight = 256, cap = 0;
472     int tslice = 0, ratelimit = 0;
473     bool opt_w = false, opt_c = false;
474     bool opt_t = false, opt_r = false;
475     bool opt_s = false;
476     int opt, rc;
477     static struct option opts[] = {
478         {"domain", 1, 0, 'd'},
479         {"weight", 1, 0, 'w'},
480         {"cap", 1, 0, 'c'},
481         {"schedparam", 0, 0, 's'},
482         {"tslice_ms", 1, 0, 't'},
483         {"ratelimit_us", 1, 0, 'r'},
484         {"cpupool", 1, 0, 'p'},
485         COMMON_LONG_OPTS
486     };
487 
488     SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:s", opts, "sched-credit", 0) {
489     case 'd':
490         dom = optarg;
491         break;
492     case 'w':
493         weight = strtol(optarg, NULL, 10);
494         opt_w = true;
495         break;
496     case 'c':
497         cap = strtol(optarg, NULL, 10);
498         opt_c = true;
499         break;
500     case 't':
501         tslice = strtol(optarg, NULL, 10);
502         opt_t = true;
503         break;
504     case 'r':
505         ratelimit = strtol(optarg, NULL, 10);
506         opt_r = true;
507         break;
508     case 's':
509         opt_s = true;
510         break;
511     case 'p':
512         cpupool = optarg;
513         break;
514     }
515 
516     if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
517         fprintf(stderr, "Specifying a cpupool or schedparam is not "
518                 "allowed with domain options.\n");
519         return EXIT_FAILURE;
520     }
521     if (!dom && (opt_w || opt_c)) {
522         fprintf(stderr, "Must specify a domain.\n");
523         return EXIT_FAILURE;
524     }
525     if (!opt_s && (opt_t || opt_r)) {
526         fprintf(stderr, "Must specify schedparam to set schedule "
527                 "parameter values.\n");
528         return EXIT_FAILURE;
529     }
530 
531     if (opt_s) {
532         libxl_sched_credit_params scparam;
533         uint32_t poolid = 0;
534 
535         if (cpupool) {
536             if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
537                                                      &poolid, NULL) ||
538                 !libxl_cpupoolid_is_valid(ctx, poolid)) {
539                 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
540                 return EXIT_FAILURE;
541             }
542         }
543 
544         if (!opt_t && !opt_r) { /* Output scheduling parameters */
545             if (sched_credit_pool_output(poolid))
546                 return EXIT_FAILURE;
547         } else { /* Set scheduling parameters*/
548             if (sched_credit_params_get(poolid, &scparam))
549                 return EXIT_FAILURE;
550 
551             if (opt_t)
552                 scparam.tslice_ms = tslice;
553 
554             if (opt_r)
555                 scparam.ratelimit_us = ratelimit;
556 
557             if (sched_credit_params_set(poolid, &scparam))
558                 return EXIT_FAILURE;
559         }
560     } else if (!dom) { /* list all domain's credit scheduler info */
561         if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
562                                 sched_credit_domain_output,
563                                 sched_credit_pool_output,
564                                 cpupool))
565             return EXIT_FAILURE;
566     } else {
567         uint32_t domid = find_domain(dom);
568 
569         if (!opt_w && !opt_c) { /* output credit scheduler info */
570             sched_credit_domain_output(-1);
571             if (sched_credit_domain_output(domid))
572                 return EXIT_FAILURE;
573         } else { /* set credit scheduler paramaters */
574             libxl_domain_sched_params scinfo;
575             libxl_domain_sched_params_init(&scinfo);
576             scinfo.sched = LIBXL_SCHEDULER_CREDIT;
577             if (opt_w)
578                 scinfo.weight = weight;
579             if (opt_c)
580                 scinfo.cap = cap;
581             rc = sched_domain_set(domid, &scinfo);
582             libxl_domain_sched_params_dispose(&scinfo);
583             if (rc)
584                 return EXIT_FAILURE;
585         }
586     }
587 
588     return EXIT_SUCCESS;
589 }
590 
main_sched_credit2(int argc,char ** argv)591 int main_sched_credit2(int argc, char **argv)
592 {
593     const char *dom = NULL;
594     const char *cpupool = NULL;
595     int ratelimit = 0;
596     int weight = 256, cap = 0;
597     bool opt_s = false;
598     bool opt_r = false;
599     bool opt_w = false;
600     bool opt_c = false;
601     int opt, rc;
602     static struct option opts[] = {
603         {"domain", 1, 0, 'd'},
604         {"weight", 1, 0, 'w'},
605         {"cap", 1, 0, 'c'},
606         {"schedparam", 0, 0, 's'},
607         {"ratelimit_us", 1, 0, 'r'},
608         {"cpupool", 1, 0, 'p'},
609         COMMON_LONG_OPTS
610     };
611 
612     SWITCH_FOREACH_OPT(opt, "d:w:c:p:r:s", opts, "sched-credit2", 0) {
613     case 'd':
614         dom = optarg;
615         break;
616     case 'w':
617         weight = strtol(optarg, NULL, 10);
618         opt_w = true;
619         break;
620     case 'c':
621         cap = strtol(optarg, NULL, 10);
622         opt_c = true;
623         break;
624     case 's':
625         opt_s = true;
626         break;
627     case 'r':
628         ratelimit = strtol(optarg, NULL, 10);
629         opt_r = true;
630         break;
631     case 'p':
632         cpupool = optarg;
633         break;
634     }
635 
636     if (cpupool && (dom || opt_w || opt_c)) {
637         fprintf(stderr, "Specifying a cpupool is not allowed with other "
638                 "options.\n");
639         return EXIT_FAILURE;
640     }
641     if (!dom && (opt_w || opt_c)) {
642         fprintf(stderr, "Must specify a domain.\n");
643         return EXIT_FAILURE;
644     }
645 
646     if (opt_s) {
647         libxl_sched_credit2_params scparam;
648         uint32_t poolid = 0;
649 
650         if (cpupool) {
651             if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
652                                                      &poolid, NULL) ||
653                 !libxl_cpupoolid_is_valid(ctx, poolid)) {
654                 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
655                 return EXIT_FAILURE;
656             }
657         }
658 
659         if (!opt_r) { /* Output scheduling parameters */
660             if (sched_credit2_pool_output(poolid))
661                 return EXIT_FAILURE;
662         } else {      /* Set scheduling parameters (so far, just ratelimit) */
663             scparam.ratelimit_us = ratelimit;
664             if (sched_credit2_params_set(poolid, &scparam))
665                 return EXIT_FAILURE;
666         }
667     } else if (!dom) { /* list all domain's credit scheduler info */
668         if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
669                                 sched_credit2_domain_output,
670                                 sched_credit2_pool_output,
671                                 cpupool))
672             return EXIT_FAILURE;
673     } else {
674         uint32_t domid = find_domain(dom);
675 
676         if (!opt_w && !opt_c) { /* output credit2 scheduler info */
677             sched_credit2_domain_output(-1);
678             if (sched_credit2_domain_output(domid))
679                 return EXIT_FAILURE;
680         } else { /* set credit2 scheduler paramaters */
681             libxl_domain_sched_params scinfo;
682             libxl_domain_sched_params_init(&scinfo);
683             scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
684             if (opt_w)
685                 scinfo.weight = weight;
686             if (opt_c)
687                 scinfo.cap = cap;
688             rc = sched_domain_set(domid, &scinfo);
689             libxl_domain_sched_params_dispose(&scinfo);
690             if (rc)
691                 return EXIT_FAILURE;
692         }
693     }
694 
695     return EXIT_SUCCESS;
696 }
697 
698 /*
699  * <nothing>            : List all domain paramters and sched params
700  * -d [domid]           : List default domain params for domain
701  * -d [domid] [params]  : Set domain params for domain
702  * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
703  * List per-VCPU params for domain
704  * -d [domid] -v all  : List all per-VCPU params for domain
705  * -v all  : List all per-VCPU params for all domains
706  * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
707  * Set per-VCPU params for domain
708  * -d [domid] -v all [params]  : Set all per-VCPU params for domain
709  */
main_sched_rtds(int argc,char ** argv)710 int main_sched_rtds(int argc, char **argv)
711 {
712     const char *dom = NULL;
713     const char *cpupool = NULL;
714     int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
715     int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
716     int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
717     bool *extratimes = (bool *)xmalloc(sizeof(bool)); /* extratime is bool */
718     int v_size = 1; /* size of vcpus array */
719     int p_size = 1; /* size of periods array */
720     int b_size = 1; /* size of budgets array */
721     int e_size = 1; /* size of extratimes array */
722     int v_index = 0; /* index in vcpus array */
723     int p_index =0; /* index in periods array */
724     int b_index =0; /* index for in budgets array */
725     int e_index = 0; /* index in extratimes array */
726     bool opt_p = false;
727     bool opt_b = false;
728     bool opt_e = false;
729     bool opt_v = false;
730     bool opt_all = false; /* output per-dom parameters */
731     int opt, i, rc, r;
732     static struct option opts[] = {
733         {"domain", 1, 0, 'd'},
734         {"period", 1, 0, 'p'},
735         {"budget", 1, 0, 'b'},
736         {"extratime", 1, 0, 'e'},
737         {"vcpuid",1, 0, 'v'},
738         {"cpupool", 1, 0, 'c'},
739         COMMON_LONG_OPTS
740     };
741 
742     SWITCH_FOREACH_OPT(opt, "d:p:b:e:v:c", opts, "sched-rtds", 0) {
743     case 'd':
744         dom = optarg;
745         break;
746     case 'p':
747         if (p_index >= p_size) {
748             /*
749              * periods array is full
750              * double the array size for new elements
751              */
752             p_size *= 2;
753             periods = xrealloc(periods, p_size);
754         }
755         periods[p_index++] = strtol(optarg, NULL, 10);
756         opt_p = 1;
757         break;
758     case 'b':
759         if (b_index >= b_size) { /* budgets array is full */
760             b_size *= 2;
761             budgets = xrealloc(budgets, b_size);
762         }
763         budgets[b_index++] = strtol(optarg, NULL, 10);
764         opt_b = 1;
765         break;
766     case 'e':
767         if (e_index >= e_size) { /* extratime array is full */
768             e_size *= 2;
769             extratimes = xrealloc(extratimes, e_size);
770         }
771         if (strcmp(optarg, "0") && strcmp(optarg, "1"))
772         {
773             fprintf(stderr, "Invalid extratime.\n");
774             r = EXIT_FAILURE;
775             goto out;
776         }
777         extratimes[e_index++] = strtol(optarg, NULL, 10);
778         opt_e = 1;
779         break;
780     case 'v':
781         if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
782             opt_all = 1;
783             break;
784         }
785         if (v_index >= v_size) { /* vcpus array is full */
786             v_size *= 2;
787             vcpus = xrealloc(vcpus, v_size);
788         }
789         vcpus[v_index++] = strtol(optarg, NULL, 10);
790         opt_v = 1;
791         break;
792     case 'c':
793         cpupool = optarg;
794         break;
795     }
796 
797     if (cpupool && (dom || opt_p || opt_b || opt_e || opt_v || opt_all)) {
798         fprintf(stderr, "Specifying a cpupool is not allowed with "
799                 "other options.\n");
800         r = EXIT_FAILURE;
801         goto out;
802     }
803     if (!dom && (opt_p || opt_b || opt_e || opt_v)) {
804         fprintf(stderr, "Missing parameters.\n");
805         r = EXIT_FAILURE;
806         goto out;
807     }
808     if (dom && !opt_v && !opt_all && (opt_p || opt_b || opt_e)) {
809         fprintf(stderr, "Must specify VCPU.\n");
810         r = EXIT_FAILURE;
811         goto out;
812     }
813     if (opt_v && opt_all) {
814         fprintf(stderr, "Incorrect VCPU IDs.\n");
815         r = EXIT_FAILURE;
816         goto out;
817     }
818     if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
819          || ((v_index > e_index) && opt_e) || p_index != b_index
820          || p_index != e_index ) {
821         fprintf(stderr, "Incorrect number of period, budget and extratime\n");
822         r = EXIT_FAILURE;
823         goto out;
824     }
825 
826     if ((!dom) && opt_all) {
827         /* get all domain's per-vcpu rtds scheduler parameters */
828         rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
829                                 sched_rtds_vcpu_output_all,
830                                 sched_rtds_pool_output,
831                                 cpupool);
832         if (rc) {
833             r = EXIT_FAILURE;
834             goto out;
835         }
836     } else if (!dom && !opt_all) {
837         /* list all domain's default scheduling parameters */
838         rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
839                                   sched_rtds_domain_output,
840                                   sched_rtds_pool_output,
841                                   cpupool);
842         if (rc) {
843             r = EXIT_FAILURE;
844             goto out;
845         }
846     } else {
847         uint32_t domid = find_domain(dom);
848         if (!opt_v && !opt_all) { /* output default scheduling parameters */
849             sched_rtds_domain_output(-1);
850             rc = -sched_rtds_domain_output(domid);
851             if (rc) {
852                 r = EXIT_FAILURE;
853                 goto out;
854             }
855         } else if (!opt_p && !opt_b && !opt_e) {
856             /* get per-vcpu rtds scheduling parameters */
857             libxl_vcpu_sched_params scinfo;
858             libxl_vcpu_sched_params_init(&scinfo);
859             sched_rtds_vcpu_output(-1, &scinfo);
860             scinfo.num_vcpus = v_index;
861             if (v_index > 0) {
862                 scinfo.vcpus = (libxl_sched_params *)
863                                xmalloc(sizeof(libxl_sched_params) * (v_index));
864                 for (i = 0; i < v_index; i++)
865                     scinfo.vcpus[i].vcpuid = vcpus[i];
866                 rc = -sched_rtds_vcpu_output(domid, &scinfo);
867             } else /* get params for all vcpus */
868                 rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
869             libxl_vcpu_sched_params_dispose(&scinfo);
870             if (rc) {
871                 r = EXIT_FAILURE;
872                 goto out;
873             }
874     } else if (opt_v || opt_all) {
875             /* set per-vcpu rtds scheduling parameters */
876             libxl_vcpu_sched_params scinfo;
877             libxl_vcpu_sched_params_init(&scinfo);
878             scinfo.sched = LIBXL_SCHEDULER_RTDS;
879             if (v_index > 0) {
880                 scinfo.num_vcpus = v_index;
881                 scinfo.vcpus = (libxl_sched_params *)
882                                xmalloc(sizeof(libxl_sched_params) * (v_index));
883                 for (i = 0; i < v_index; i++) {
884                     scinfo.vcpus[i].vcpuid = vcpus[i];
885                     scinfo.vcpus[i].period = periods[i];
886                     scinfo.vcpus[i].budget = budgets[i];
887                     scinfo.vcpus[i].extratime = extratimes[i] ? 1 : 0;
888                 }
889                 rc = sched_vcpu_set(domid, &scinfo);
890             } else { /* set params for all vcpus */
891                 scinfo.num_vcpus = 1;
892                 scinfo.vcpus = (libxl_sched_params *)
893                                xmalloc(sizeof(libxl_sched_params));
894                 scinfo.vcpus[0].period = periods[0];
895                 scinfo.vcpus[0].budget = budgets[0];
896                 scinfo.vcpus[0].extratime = extratimes[0] ? 1 : 0;
897                 rc = sched_vcpu_set_all(domid, &scinfo);
898             }
899 
900             libxl_vcpu_sched_params_dispose(&scinfo);
901             if (rc) {
902                 r = EXIT_FAILURE;
903                 goto out;
904             }
905         }
906     }
907 
908     r = EXIT_SUCCESS;
909 out:
910     free(vcpus);
911     free(periods);
912     free(budgets);
913     free(extratimes);
914     return r;
915 }
916 
917 /*
918  * Local variables:
919  * mode: C
920  * c-basic-offset: 4
921  * indent-tabs-mode: nil
922  * End:
923  */
924