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 migration-delay=%dus\n",
176                poolname,
177                scparam.tslice_ms,
178                scparam.ratelimit_us,
179                scparam.vcpu_migr_delay_us);
180     }
181     free(poolname);
182     return 0;
183 }
184 
sched_credit2_params_set(int poolid,libxl_sched_credit2_params * scinfo)185 static int sched_credit2_params_set(int poolid,
186                                     libxl_sched_credit2_params *scinfo)
187 {
188     if (libxl_sched_credit2_params_set(ctx, poolid, scinfo)) {
189         fprintf(stderr, "libxl_sched_credit2_params_set failed.\n");
190         return 1;
191     }
192 
193     return 0;
194 }
195 
sched_credit2_params_get(int poolid,libxl_sched_credit2_params * scinfo)196 static int sched_credit2_params_get(int poolid,
197                                     libxl_sched_credit2_params *scinfo)
198 {
199     if (libxl_sched_credit2_params_get(ctx, poolid, scinfo)) {
200         fprintf(stderr, "libxl_sched_credit2_params_get failed.\n");
201         return 1;
202     }
203 
204     return 0;
205 }
206 
sched_credit2_domain_output(int domid)207 static int sched_credit2_domain_output(int domid)
208 {
209     char *domname;
210     libxl_domain_sched_params scinfo;
211 
212     if (domid < 0) {
213         printf("%-33s %4s %6s %4s\n", "Name", "ID", "Weight", "Cap");
214         return 0;
215     }
216 
217     libxl_domain_sched_params_init(&scinfo);
218     if (sched_domain_get(LIBXL_SCHEDULER_CREDIT2, domid, &scinfo)) {
219         libxl_domain_sched_params_dispose(&scinfo);
220         return 1;
221     }
222     domname = libxl_domid_to_name(ctx, domid);
223     printf("%-33s %4d %6d %4d\n",
224         domname,
225         domid,
226         scinfo.weight,
227         scinfo.cap);
228     free(domname);
229     libxl_domain_sched_params_dispose(&scinfo);
230     return 0;
231 }
232 
sched_credit2_pool_output(uint32_t poolid)233 static int sched_credit2_pool_output(uint32_t poolid)
234 {
235     libxl_sched_credit2_params scparam;
236     char *poolname = libxl_cpupoolid_to_name(ctx, poolid);
237 
238     if (sched_credit2_params_get(poolid, &scparam))
239         printf("Cpupool %s: [sched params unavailable]\n", poolname);
240     else
241         printf("Cpupool %s: ratelimit=%dus\n",
242                poolname, scparam.ratelimit_us);
243 
244     free(poolname);
245 
246     return 0;
247 }
248 
sched_rtds_domain_output(int domid)249 static int sched_rtds_domain_output(
250     int domid)
251 {
252     char *domname;
253     libxl_domain_sched_params scinfo;
254 
255     if (domid < 0) {
256         printf("%-33s %4s %9s %9s %10s\n", "Name", "ID", "Period", "Budget", "Extratime");
257         return 0;
258     }
259 
260     libxl_domain_sched_params_init(&scinfo);
261     if (sched_domain_get(LIBXL_SCHEDULER_RTDS, domid, &scinfo)) {
262         libxl_domain_sched_params_dispose(&scinfo);
263         return 1;
264     }
265 
266     domname = libxl_domid_to_name(ctx, domid);
267     printf("%-33s %4d %9d %9d %10s\n",
268         domname,
269         domid,
270         scinfo.period,
271         scinfo.budget,
272         scinfo.extratime ? "yes" : "no");
273     free(domname);
274     libxl_domain_sched_params_dispose(&scinfo);
275     return 0;
276 }
277 
sched_rtds_vcpu_output(int domid,libxl_vcpu_sched_params * scinfo)278 static int sched_rtds_vcpu_output(int domid, libxl_vcpu_sched_params *scinfo)
279 {
280     char *domname;
281     int rc = 0;
282     int i;
283 
284     if (domid < 0) {
285         printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
286                "VCPU", "Period", "Budget", "Extratime");
287         return 0;
288     }
289 
290     rc = sched_vcpu_get(LIBXL_SCHEDULER_RTDS, domid, scinfo);
291     if (rc)
292         return 1;
293 
294     domname = libxl_domid_to_name(ctx, domid);
295     for ( i = 0; i < scinfo->num_vcpus; i++ ) {
296         printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
297                domname,
298                domid,
299                scinfo->vcpus[i].vcpuid,
300                scinfo->vcpus[i].period,
301                scinfo->vcpus[i].budget,
302                scinfo->vcpus[i].extratime ? "yes" : "no");
303     }
304     free(domname);
305     return 0;
306 }
307 
sched_rtds_vcpu_output_all(int domid,libxl_vcpu_sched_params * scinfo)308 static int sched_rtds_vcpu_output_all(int domid,
309                                       libxl_vcpu_sched_params *scinfo)
310 {
311     char *domname;
312     int rc = 0;
313     int i;
314 
315     if (domid < 0) {
316         printf("%-33s %4s %4s %9s %9s %10s\n", "Name", "ID",
317                "VCPU", "Period", "Budget", "Extratime");
318         return 0;
319     }
320 
321     scinfo->num_vcpus = 0;
322     rc = sched_vcpu_get_all(LIBXL_SCHEDULER_RTDS, domid, scinfo);
323     if (rc)
324         return 1;
325 
326     domname = libxl_domid_to_name(ctx, domid);
327     for ( i = 0; i < scinfo->num_vcpus; i++ ) {
328         printf("%-33s %4d %4d %9"PRIu32" %9"PRIu32" %10s\n",
329                domname,
330                domid,
331                scinfo->vcpus[i].vcpuid,
332                scinfo->vcpus[i].period,
333                scinfo->vcpus[i].budget,
334                scinfo->vcpus[i].extratime ? "yes" : "no");
335     }
336     free(domname);
337     return 0;
338 }
339 
sched_rtds_pool_output(uint32_t poolid)340 static int sched_rtds_pool_output(uint32_t poolid)
341 {
342     char *poolname;
343 
344     poolname = libxl_cpupoolid_to_name(ctx, poolid);
345     printf("Cpupool %s: sched=RTDS\n", poolname);
346 
347     free(poolname);
348     return 0;
349 }
350 
sched_domain_output(libxl_scheduler sched,int (* output)(int),int (* pooloutput)(uint32_t),const char * cpupool)351 static int sched_domain_output(libxl_scheduler sched, int (*output)(int),
352                                int (*pooloutput)(uint32_t), const char *cpupool)
353 {
354     libxl_dominfo *info;
355     libxl_cpupoolinfo *poolinfo = NULL;
356     uint32_t poolid;
357     int nb_domain, n_pools = 0, i, p;
358     int rc = 0;
359 
360     if (cpupool) {
361         if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL) ||
362             !libxl_cpupoolid_is_valid(ctx, poolid)) {
363             fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
364             return 1;
365         }
366     }
367 
368     info = libxl_list_domain(ctx, &nb_domain);
369     if (!info) {
370         fprintf(stderr, "libxl_list_domain failed.\n");
371         return 1;
372     }
373     poolinfo = libxl_list_cpupool(ctx, &n_pools);
374     if (!poolinfo) {
375         fprintf(stderr, "error getting cpupool info\n");
376         libxl_dominfo_list_free(info, nb_domain);
377         return 1;
378     }
379 
380     for (p = 0; !rc && (p < n_pools); p++) {
381         if ((poolinfo[p].sched != sched) ||
382             (cpupool && (poolid != poolinfo[p].poolid)))
383             continue;
384 
385         pooloutput(poolinfo[p].poolid);
386 
387         output(-1);
388         for (i = 0; i < nb_domain; i++) {
389             if (info[i].cpupool != poolinfo[p].poolid)
390                 continue;
391             rc = output(info[i].domid);
392             if (rc)
393                 break;
394         }
395     }
396 
397     libxl_cpupoolinfo_list_free(poolinfo, n_pools);
398     libxl_dominfo_list_free(info, nb_domain);
399     return 0;
400 }
401 
sched_vcpu_output(libxl_scheduler sched,int (* output)(int,libxl_vcpu_sched_params *),int (* pooloutput)(uint32_t),const char * cpupool)402 static int sched_vcpu_output(libxl_scheduler sched,
403                              int (*output)(int, libxl_vcpu_sched_params *),
404                              int (*pooloutput)(uint32_t), const char *cpupool)
405 {
406     libxl_dominfo *info;
407     libxl_cpupoolinfo *poolinfo = NULL;
408     uint32_t poolid;
409     int nb_domain, n_pools = 0, i, p;
410     int rc = 0;
411 
412     if (cpupool) {
413         if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool, &poolid, NULL)
414             || !libxl_cpupoolid_is_valid(ctx, poolid)) {
415             fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
416             return 1;
417         }
418     }
419 
420     info = libxl_list_domain(ctx, &nb_domain);
421     if (!info) {
422         fprintf(stderr, "libxl_list_domain failed.\n");
423         return 1;
424     }
425     poolinfo = libxl_list_cpupool(ctx, &n_pools);
426     if (!poolinfo) {
427         fprintf(stderr, "error getting cpupool info\n");
428         libxl_dominfo_list_free(info, nb_domain);
429         return 1;
430     }
431 
432     for (p = 0; !rc && (p < n_pools); p++) {
433         if ((poolinfo[p].sched != sched) ||
434             (cpupool && (poolid != poolinfo[p].poolid)))
435             continue;
436 
437         pooloutput(poolinfo[p].poolid);
438 
439         output(-1, NULL);
440         for (i = 0; i < nb_domain; i++) {
441             libxl_vcpu_sched_params scinfo;
442             if (info[i].cpupool != poolinfo[p].poolid)
443                 continue;
444             libxl_vcpu_sched_params_init(&scinfo);
445             rc = output(info[i].domid, &scinfo);
446             libxl_vcpu_sched_params_dispose(&scinfo);
447             if (rc)
448                 break;
449         }
450     }
451 
452     libxl_cpupoolinfo_list_free(poolinfo, n_pools);
453     libxl_dominfo_list_free(info, nb_domain);
454     return 0;
455 }
456 
457 /*
458  * <nothing>             : List all domain params and sched params from all pools
459  * -d [domid]            : List domain params for domain
460  * -d [domid] [params]   : Set domain params for domain
461  * -p [pool]             : list all domains and sched params for pool
462  * -s                    : List sched params for poolid 0
463  * -s [params]           : Set sched params for poolid 0
464  * -p [pool] -s          : List sched params for pool
465  * -p [pool] -s [params] : Set sched params for pool
466  * -p [pool] -d...       : Illegal
467  */
main_sched_credit(int argc,char ** argv)468 int main_sched_credit(int argc, char **argv)
469 {
470     const char *dom = NULL;
471     const char *cpupool = NULL;
472     int weight = 256, cap = 0;
473     int tslice = 0, ratelimit = 0, migrdelay = 0;
474     bool opt_w = false, opt_c = false;
475     bool opt_t = false, opt_r = false;
476     bool opt_s = false, opt_m = false;
477     int opt, rc;
478     static struct option opts[] = {
479         {"domain", 1, 0, 'd'},
480         {"weight", 1, 0, 'w'},
481         {"cap", 1, 0, 'c'},
482         {"schedparam", 0, 0, 's'},
483         {"tslice_ms", 1, 0, 't'},
484         {"ratelimit_us", 1, 0, 'r'},
485         {"migration_delay_us", 1, 0, 'm'},
486         {"cpupool", 1, 0, 'p'},
487         COMMON_LONG_OPTS
488     };
489 
490     SWITCH_FOREACH_OPT(opt, "d:w:c:p:t:r:m:s", opts, "sched-credit", 0) {
491     case 'd':
492         dom = optarg;
493         break;
494     case 'w':
495         weight = strtol(optarg, NULL, 10);
496         opt_w = true;
497         break;
498     case 'c':
499         cap = strtol(optarg, NULL, 10);
500         opt_c = true;
501         break;
502     case 't':
503         tslice = strtol(optarg, NULL, 10);
504         opt_t = true;
505         break;
506     case 'r':
507         ratelimit = strtol(optarg, NULL, 10);
508         opt_r = true;
509         break;
510     case 'm':
511         migrdelay = strtol(optarg, NULL, 10);
512         opt_m = true;
513         break;
514     case 's':
515         opt_s = true;
516         break;
517     case 'p':
518         cpupool = optarg;
519         break;
520     }
521 
522     if ((cpupool || opt_s) && (dom || opt_w || opt_c)) {
523         fprintf(stderr, "Specifying a cpupool or schedparam is not "
524                 "allowed with domain options.\n");
525         return EXIT_FAILURE;
526     }
527     if (!dom && (opt_w || opt_c)) {
528         fprintf(stderr, "Must specify a domain.\n");
529         return EXIT_FAILURE;
530     }
531     if (!opt_s && (opt_t || opt_r || opt_m)) {
532         fprintf(stderr, "Must specify schedparam to set schedule "
533                 "parameter values.\n");
534         return EXIT_FAILURE;
535     }
536 
537     if (opt_s) {
538         libxl_sched_credit_params scparam;
539         uint32_t poolid = 0;
540 
541         if (cpupool) {
542             if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
543                                                      &poolid, NULL) ||
544                 !libxl_cpupoolid_is_valid(ctx, poolid)) {
545                 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
546                 return EXIT_FAILURE;
547             }
548         }
549 
550         if (!opt_t && !opt_r && !opt_m) { /* Output scheduling parameters */
551             if (sched_credit_pool_output(poolid))
552                 return EXIT_FAILURE;
553         } else { /* Set scheduling parameters*/
554             if (sched_credit_params_get(poolid, &scparam))
555                 return EXIT_FAILURE;
556 
557             if (opt_t)
558                 scparam.tslice_ms = tslice;
559 
560             if (opt_r)
561                 scparam.ratelimit_us = ratelimit;
562 
563             if (opt_m)
564                 scparam.vcpu_migr_delay_us = migrdelay;
565 
566             if (sched_credit_params_set(poolid, &scparam))
567                 return EXIT_FAILURE;
568         }
569     } else if (!dom) { /* list all domain's credit scheduler info */
570         if (sched_domain_output(LIBXL_SCHEDULER_CREDIT,
571                                 sched_credit_domain_output,
572                                 sched_credit_pool_output,
573                                 cpupool))
574             return EXIT_FAILURE;
575     } else {
576         uint32_t domid = find_domain(dom);
577 
578         if (!opt_w && !opt_c) { /* output credit scheduler info */
579             sched_credit_domain_output(-1);
580             if (sched_credit_domain_output(domid))
581                 return EXIT_FAILURE;
582         } else { /* set credit scheduler paramaters */
583             libxl_domain_sched_params scinfo;
584             libxl_domain_sched_params_init(&scinfo);
585             scinfo.sched = LIBXL_SCHEDULER_CREDIT;
586             if (opt_w)
587                 scinfo.weight = weight;
588             if (opt_c)
589                 scinfo.cap = cap;
590             rc = sched_domain_set(domid, &scinfo);
591             libxl_domain_sched_params_dispose(&scinfo);
592             if (rc)
593                 return EXIT_FAILURE;
594         }
595     }
596 
597     return EXIT_SUCCESS;
598 }
599 
main_sched_credit2(int argc,char ** argv)600 int main_sched_credit2(int argc, char **argv)
601 {
602     const char *dom = NULL;
603     const char *cpupool = NULL;
604     int ratelimit = 0;
605     int weight = 256, cap = 0;
606     bool opt_s = false;
607     bool opt_r = false;
608     bool opt_w = false;
609     bool opt_c = false;
610     int opt, rc;
611     static struct option opts[] = {
612         {"domain", 1, 0, 'd'},
613         {"weight", 1, 0, 'w'},
614         {"cap", 1, 0, 'c'},
615         {"schedparam", 0, 0, 's'},
616         {"ratelimit_us", 1, 0, 'r'},
617         {"cpupool", 1, 0, 'p'},
618         COMMON_LONG_OPTS
619     };
620 
621     SWITCH_FOREACH_OPT(opt, "d:w:c:p:r:s", opts, "sched-credit2", 0) {
622     case 'd':
623         dom = optarg;
624         break;
625     case 'w':
626         weight = strtol(optarg, NULL, 10);
627         opt_w = true;
628         break;
629     case 'c':
630         cap = strtol(optarg, NULL, 10);
631         opt_c = true;
632         break;
633     case 's':
634         opt_s = true;
635         break;
636     case 'r':
637         ratelimit = strtol(optarg, NULL, 10);
638         opt_r = true;
639         break;
640     case 'p':
641         cpupool = optarg;
642         break;
643     }
644 
645     if (cpupool && (dom || opt_w || opt_c)) {
646         fprintf(stderr, "Specifying a cpupool is not allowed with other "
647                 "options.\n");
648         return EXIT_FAILURE;
649     }
650     if (!dom && (opt_w || opt_c)) {
651         fprintf(stderr, "Must specify a domain.\n");
652         return EXIT_FAILURE;
653     }
654 
655     if (opt_s) {
656         libxl_sched_credit2_params scparam;
657         uint32_t poolid = 0;
658 
659         if (cpupool) {
660             if (libxl_cpupool_qualifier_to_cpupoolid(ctx, cpupool,
661                                                      &poolid, NULL) ||
662                 !libxl_cpupoolid_is_valid(ctx, poolid)) {
663                 fprintf(stderr, "unknown cpupool \'%s\'\n", cpupool);
664                 return EXIT_FAILURE;
665             }
666         }
667 
668         if (!opt_r) { /* Output scheduling parameters */
669             if (sched_credit2_pool_output(poolid))
670                 return EXIT_FAILURE;
671         } else {      /* Set scheduling parameters (so far, just ratelimit) */
672             scparam.ratelimit_us = ratelimit;
673             if (sched_credit2_params_set(poolid, &scparam))
674                 return EXIT_FAILURE;
675         }
676     } else if (!dom) { /* list all domain's credit scheduler info */
677         if (sched_domain_output(LIBXL_SCHEDULER_CREDIT2,
678                                 sched_credit2_domain_output,
679                                 sched_credit2_pool_output,
680                                 cpupool))
681             return EXIT_FAILURE;
682     } else {
683         uint32_t domid = find_domain(dom);
684 
685         if (!opt_w && !opt_c) { /* output credit2 scheduler info */
686             sched_credit2_domain_output(-1);
687             if (sched_credit2_domain_output(domid))
688                 return EXIT_FAILURE;
689         } else { /* set credit2 scheduler paramaters */
690             libxl_domain_sched_params scinfo;
691             libxl_domain_sched_params_init(&scinfo);
692             scinfo.sched = LIBXL_SCHEDULER_CREDIT2;
693             if (opt_w)
694                 scinfo.weight = weight;
695             if (opt_c)
696                 scinfo.cap = cap;
697             rc = sched_domain_set(domid, &scinfo);
698             libxl_domain_sched_params_dispose(&scinfo);
699             if (rc)
700                 return EXIT_FAILURE;
701         }
702     }
703 
704     return EXIT_SUCCESS;
705 }
706 
707 /*
708  * <nothing>            : List all domain paramters and sched params
709  * -d [domid]           : List default domain params for domain
710  * -d [domid] [params]  : Set domain params for domain
711  * -d [domid] -v [vcpuid 1] -v [vcpuid 2] ...  :
712  * List per-VCPU params for domain
713  * -d [domid] -v all  : List all per-VCPU params for domain
714  * -v all  : List all per-VCPU params for all domains
715  * -d [domid] -v [vcpuid 1] [params] -v [vcpuid 2] [params] ...  :
716  * Set per-VCPU params for domain
717  * -d [domid] -v all [params]  : Set all per-VCPU params for domain
718  */
main_sched_rtds(int argc,char ** argv)719 int main_sched_rtds(int argc, char **argv)
720 {
721     const char *dom = NULL;
722     const char *cpupool = NULL;
723     int *vcpus = (int *)xmalloc(sizeof(int)); /* IDs of VCPUs that change */
724     int *periods = (int *)xmalloc(sizeof(int)); /* period is in microsecond */
725     int *budgets = (int *)xmalloc(sizeof(int)); /* budget is in microsecond */
726     bool *extratimes = (bool *)xmalloc(sizeof(bool)); /* extratime is bool */
727     int v_size = 1; /* size of vcpus array */
728     int p_size = 1; /* size of periods array */
729     int b_size = 1; /* size of budgets array */
730     int e_size = 1; /* size of extratimes array */
731     int v_index = 0; /* index in vcpus array */
732     int p_index =0; /* index in periods array */
733     int b_index =0; /* index for in budgets array */
734     int e_index = 0; /* index in extratimes array */
735     bool opt_p = false;
736     bool opt_b = false;
737     bool opt_e = false;
738     bool opt_v = false;
739     bool opt_all = false; /* output per-dom parameters */
740     int opt, i, rc, r;
741     static struct option opts[] = {
742         {"domain", 1, 0, 'd'},
743         {"period", 1, 0, 'p'},
744         {"budget", 1, 0, 'b'},
745         {"extratime", 1, 0, 'e'},
746         {"vcpuid",1, 0, 'v'},
747         {"cpupool", 1, 0, 'c'},
748         COMMON_LONG_OPTS
749     };
750 
751     SWITCH_FOREACH_OPT(opt, "d:p:b:e:v:c", opts, "sched-rtds", 0) {
752     case 'd':
753         dom = optarg;
754         break;
755     case 'p':
756         if (p_index >= p_size) {
757             /*
758              * periods array is full
759              * double the array size for new elements
760              */
761             p_size *= 2;
762             periods = xrealloc(periods, p_size);
763         }
764         periods[p_index++] = strtol(optarg, NULL, 10);
765         opt_p = 1;
766         break;
767     case 'b':
768         if (b_index >= b_size) { /* budgets array is full */
769             b_size *= 2;
770             budgets = xrealloc(budgets, b_size);
771         }
772         budgets[b_index++] = strtol(optarg, NULL, 10);
773         opt_b = 1;
774         break;
775     case 'e':
776         if (e_index >= e_size) { /* extratime array is full */
777             e_size *= 2;
778             extratimes = xrealloc(extratimes, e_size);
779         }
780         if (strcmp(optarg, "0") && strcmp(optarg, "1"))
781         {
782             fprintf(stderr, "Invalid extratime.\n");
783             r = EXIT_FAILURE;
784             goto out;
785         }
786         extratimes[e_index++] = strtol(optarg, NULL, 10);
787         opt_e = 1;
788         break;
789     case 'v':
790         if (!strcmp(optarg, "all")) { /* get or set all vcpus of a domain */
791             opt_all = 1;
792             break;
793         }
794         if (v_index >= v_size) { /* vcpus array is full */
795             v_size *= 2;
796             vcpus = xrealloc(vcpus, v_size);
797         }
798         vcpus[v_index++] = strtol(optarg, NULL, 10);
799         opt_v = 1;
800         break;
801     case 'c':
802         cpupool = optarg;
803         break;
804     }
805 
806     if (cpupool && (dom || opt_p || opt_b || opt_e || opt_v || opt_all)) {
807         fprintf(stderr, "Specifying a cpupool is not allowed with "
808                 "other options.\n");
809         r = EXIT_FAILURE;
810         goto out;
811     }
812     if (!dom && (opt_p || opt_b || opt_e || opt_v)) {
813         fprintf(stderr, "Missing parameters.\n");
814         r = EXIT_FAILURE;
815         goto out;
816     }
817     if (dom && !opt_v && !opt_all && (opt_p || opt_b || opt_e)) {
818         fprintf(stderr, "Must specify VCPU.\n");
819         r = EXIT_FAILURE;
820         goto out;
821     }
822     if (opt_v && opt_all) {
823         fprintf(stderr, "Incorrect VCPU IDs.\n");
824         r = EXIT_FAILURE;
825         goto out;
826     }
827     if (((v_index > b_index) && opt_b) || ((v_index > p_index) && opt_p)
828          || ((v_index > e_index) && opt_e) || p_index != b_index
829          || p_index != e_index ) {
830         fprintf(stderr, "Incorrect number of period, budget and extratime\n");
831         r = EXIT_FAILURE;
832         goto out;
833     }
834 
835     if ((!dom) && opt_all) {
836         /* get all domain's per-vcpu rtds scheduler parameters */
837         rc = -sched_vcpu_output(LIBXL_SCHEDULER_RTDS,
838                                 sched_rtds_vcpu_output_all,
839                                 sched_rtds_pool_output,
840                                 cpupool);
841         if (rc) {
842             r = EXIT_FAILURE;
843             goto out;
844         }
845     } else if (!dom && !opt_all) {
846         /* list all domain's default scheduling parameters */
847         rc = -sched_domain_output(LIBXL_SCHEDULER_RTDS,
848                                   sched_rtds_domain_output,
849                                   sched_rtds_pool_output,
850                                   cpupool);
851         if (rc) {
852             r = EXIT_FAILURE;
853             goto out;
854         }
855     } else {
856         uint32_t domid = find_domain(dom);
857         if (!opt_v && !opt_all) { /* output default scheduling parameters */
858             sched_rtds_domain_output(-1);
859             rc = -sched_rtds_domain_output(domid);
860             if (rc) {
861                 r = EXIT_FAILURE;
862                 goto out;
863             }
864         } else if (!opt_p && !opt_b && !opt_e) {
865             /* get per-vcpu rtds scheduling parameters */
866             libxl_vcpu_sched_params scinfo;
867             libxl_vcpu_sched_params_init(&scinfo);
868             sched_rtds_vcpu_output(-1, &scinfo);
869             scinfo.num_vcpus = v_index;
870             if (v_index > 0) {
871                 scinfo.vcpus = (libxl_sched_params *)
872                                xmalloc(sizeof(libxl_sched_params) * (v_index));
873                 for (i = 0; i < v_index; i++)
874                     scinfo.vcpus[i].vcpuid = vcpus[i];
875                 rc = -sched_rtds_vcpu_output(domid, &scinfo);
876             } else /* get params for all vcpus */
877                 rc = -sched_rtds_vcpu_output_all(domid, &scinfo);
878             libxl_vcpu_sched_params_dispose(&scinfo);
879             if (rc) {
880                 r = EXIT_FAILURE;
881                 goto out;
882             }
883     } else if (opt_v || opt_all) {
884             /* set per-vcpu rtds scheduling parameters */
885             libxl_vcpu_sched_params scinfo;
886             libxl_vcpu_sched_params_init(&scinfo);
887             scinfo.sched = LIBXL_SCHEDULER_RTDS;
888             if (v_index > 0) {
889                 scinfo.num_vcpus = v_index;
890                 scinfo.vcpus = (libxl_sched_params *)
891                                xmalloc(sizeof(libxl_sched_params) * (v_index));
892                 for (i = 0; i < v_index; i++) {
893                     scinfo.vcpus[i].vcpuid = vcpus[i];
894                     scinfo.vcpus[i].period = periods[i];
895                     scinfo.vcpus[i].budget = budgets[i];
896                     scinfo.vcpus[i].extratime = extratimes[i] ? 1 : 0;
897                 }
898                 rc = sched_vcpu_set(domid, &scinfo);
899             } else { /* set params for all vcpus */
900                 scinfo.num_vcpus = 1;
901                 scinfo.vcpus = (libxl_sched_params *)
902                                xmalloc(sizeof(libxl_sched_params));
903                 scinfo.vcpus[0].period = periods[0];
904                 scinfo.vcpus[0].budget = budgets[0];
905                 scinfo.vcpus[0].extratime = extratimes[0] ? 1 : 0;
906                 rc = sched_vcpu_set_all(domid, &scinfo);
907             }
908 
909             libxl_vcpu_sched_params_dispose(&scinfo);
910             if (rc) {
911                 r = EXIT_FAILURE;
912                 goto out;
913             }
914         }
915     }
916 
917     r = EXIT_SUCCESS;
918 out:
919     free(vcpus);
920     free(periods);
921     free(budgets);
922     free(extratimes);
923     return r;
924 }
925 
926 /*
927  * Local variables:
928  * mode: C
929  * c-basic-offset: 4
930  * indent-tabs-mode: nil
931  * End:
932  */
933