xref: /qemu/migration/options.c (revision 61a174e227422790f1b264fed6df5c6686757edc)
1 /*
2  * QEMU migration capabilities
3  *
4  * Copyright (c) 2012-2023 Red Hat Inc
5  *
6  * Authors:
7  *   Orit Wasserman <owasserm@redhat.com>
8  *   Juan Quintela <quintela@redhat.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13 
14 #include "qemu/osdep.h"
15 #include "exec/target_page.h"
16 #include "qapi/clone-visitor.h"
17 #include "qapi/error.h"
18 #include "qapi/qapi-commands-migration.h"
19 #include "qapi/qapi-visit-migration.h"
20 #include "qapi/qmp/qerror.h"
21 #include "qapi/qmp/qnull.h"
22 #include "sysemu/runstate.h"
23 #include "migration/colo.h"
24 #include "migration/misc.h"
25 #include "migration.h"
26 #include "qemu-file.h"
27 #include "ram.h"
28 #include "options.h"
29 
30 /* Maximum migrate downtime set to 2000 seconds */
31 #define MAX_MIGRATE_DOWNTIME_SECONDS 2000
32 #define MAX_MIGRATE_DOWNTIME (MAX_MIGRATE_DOWNTIME_SECONDS * 1000)
33 
34 bool migrate_auto_converge(void)
35 {
36     MigrationState *s;
37 
38     s = migrate_get_current();
39 
40     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
41 }
42 
43 bool migrate_background_snapshot(void)
44 {
45     MigrationState *s;
46 
47     s = migrate_get_current();
48 
49     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
50 }
51 
52 bool migrate_block(void)
53 {
54     MigrationState *s;
55 
56     s = migrate_get_current();
57 
58     return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
59 }
60 
61 bool migrate_colo(void)
62 {
63     MigrationState *s = migrate_get_current();
64     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
65 }
66 
67 bool migrate_compress(void)
68 {
69     MigrationState *s;
70 
71     s = migrate_get_current();
72 
73     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
74 }
75 
76 bool migrate_dirty_bitmaps(void)
77 {
78     MigrationState *s;
79 
80     s = migrate_get_current();
81 
82     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
83 }
84 
85 bool migrate_events(void)
86 {
87     MigrationState *s;
88 
89     s = migrate_get_current();
90 
91     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
92 }
93 
94 bool migrate_ignore_shared(void)
95 {
96     MigrationState *s;
97 
98     s = migrate_get_current();
99 
100     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
101 }
102 
103 bool migrate_late_block_activate(void)
104 {
105     MigrationState *s;
106 
107     s = migrate_get_current();
108 
109     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
110 }
111 
112 bool migrate_multifd(void)
113 {
114     MigrationState *s;
115 
116     s = migrate_get_current();
117 
118     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
119 }
120 
121 bool migrate_pause_before_switchover(void)
122 {
123     MigrationState *s;
124 
125     s = migrate_get_current();
126 
127     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
128 }
129 
130 bool migrate_postcopy_blocktime(void)
131 {
132     MigrationState *s;
133 
134     s = migrate_get_current();
135 
136     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
137 }
138 
139 bool migrate_postcopy_preempt(void)
140 {
141     MigrationState *s;
142 
143     s = migrate_get_current();
144 
145     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
146 }
147 
148 bool migrate_postcopy_ram(void)
149 {
150     MigrationState *s;
151 
152     s = migrate_get_current();
153 
154     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
155 }
156 
157 bool migrate_rdma_pin_all(void)
158 {
159     MigrationState *s = migrate_get_current();
160 
161     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
162 }
163 
164 bool migrate_release_ram(void)
165 {
166     MigrationState *s;
167 
168     s = migrate_get_current();
169 
170     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
171 }
172 
173 bool migrate_return_path(void)
174 {
175     MigrationState *s;
176 
177     s = migrate_get_current();
178 
179     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
180 }
181 
182 bool migrate_validate_uuid(void)
183 {
184     MigrationState *s;
185 
186     s = migrate_get_current();
187 
188     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
189 }
190 
191 bool migrate_xbzrle(void)
192 {
193     MigrationState *s;
194 
195     s = migrate_get_current();
196 
197     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
198 }
199 
200 bool migrate_zero_blocks(void)
201 {
202     MigrationState *s;
203 
204     s = migrate_get_current();
205 
206     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
207 }
208 
209 bool migrate_zero_copy_send(void)
210 {
211     MigrationState *s;
212 
213     s = migrate_get_current();
214 
215     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
216 }
217 
218 /* pseudo capabilities */
219 
220 bool migrate_postcopy(void)
221 {
222     return migrate_postcopy_ram() || migrate_dirty_bitmaps();
223 }
224 
225 bool migrate_tls(void)
226 {
227     MigrationState *s;
228 
229     s = migrate_get_current();
230 
231     return s->parameters.tls_creds && *s->parameters.tls_creds;
232 }
233 
234 typedef enum WriteTrackingSupport {
235     WT_SUPPORT_UNKNOWN = 0,
236     WT_SUPPORT_ABSENT,
237     WT_SUPPORT_AVAILABLE,
238     WT_SUPPORT_COMPATIBLE
239 } WriteTrackingSupport;
240 
241 static
242 WriteTrackingSupport migrate_query_write_tracking(void)
243 {
244     /* Check if kernel supports required UFFD features */
245     if (!ram_write_tracking_available()) {
246         return WT_SUPPORT_ABSENT;
247     }
248     /*
249      * Check if current memory configuration is
250      * compatible with required UFFD features.
251      */
252     if (!ram_write_tracking_compatible()) {
253         return WT_SUPPORT_AVAILABLE;
254     }
255 
256     return WT_SUPPORT_COMPATIBLE;
257 }
258 
259 /* Migration capabilities set */
260 struct MigrateCapsSet {
261     int size;                       /* Capability set size */
262     MigrationCapability caps[];     /* Variadic array of capabilities */
263 };
264 typedef struct MigrateCapsSet MigrateCapsSet;
265 
266 /* Define and initialize MigrateCapsSet */
267 #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
268     MigrateCapsSet _name = {    \
269         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
270         .caps = { __VA_ARGS__ } \
271     }
272 
273 /* Background-snapshot compatibility check list */
274 static const
275 INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
276     MIGRATION_CAPABILITY_POSTCOPY_RAM,
277     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
278     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
279     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
280     MIGRATION_CAPABILITY_RETURN_PATH,
281     MIGRATION_CAPABILITY_MULTIFD,
282     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
283     MIGRATION_CAPABILITY_AUTO_CONVERGE,
284     MIGRATION_CAPABILITY_RELEASE_RAM,
285     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
286     MIGRATION_CAPABILITY_COMPRESS,
287     MIGRATION_CAPABILITY_XBZRLE,
288     MIGRATION_CAPABILITY_X_COLO,
289     MIGRATION_CAPABILITY_VALIDATE_UUID,
290     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
291 
292 /**
293  * @migration_caps_check - check capability compatibility
294  *
295  * @old_caps: old capability list
296  * @new_caps: new capability list
297  * @errp: set *errp if the check failed, with reason
298  *
299  * Returns true if check passed, otherwise false.
300  */
301 bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
302 {
303     MigrationIncomingState *mis = migration_incoming_get_current();
304 
305     ERRP_GUARD();
306 #ifndef CONFIG_LIVE_BLOCK_MIGRATION
307     if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
308         error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
309                    "block migration");
310         error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
311         return false;
312     }
313 #endif
314 
315 #ifndef CONFIG_REPLICATION
316     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
317         error_setg(errp, "QEMU compiled without replication module"
318                    " can't enable COLO");
319         error_append_hint(errp, "Please enable replication before COLO.\n");
320         return false;
321     }
322 #endif
323 
324     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
325         /* This check is reasonably expensive, so only when it's being
326          * set the first time, also it's only the destination that needs
327          * special support.
328          */
329         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
330             runstate_check(RUN_STATE_INMIGRATE) &&
331             !postcopy_ram_supported_by_host(mis, errp)) {
332             error_prepend(errp, "Postcopy is not supported: ");
333             return false;
334         }
335 
336         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
337             error_setg(errp, "Postcopy is not compatible with ignore-shared");
338             return false;
339         }
340 
341         if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
342             error_setg(errp, "Postcopy is not yet compatible with multifd");
343             return false;
344         }
345     }
346 
347     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
348         WriteTrackingSupport wt_support;
349         int idx;
350         /*
351          * Check if 'background-snapshot' capability is supported by
352          * host kernel and compatible with guest memory configuration.
353          */
354         wt_support = migrate_query_write_tracking();
355         if (wt_support < WT_SUPPORT_AVAILABLE) {
356             error_setg(errp, "Background-snapshot is not supported by host kernel");
357             return false;
358         }
359         if (wt_support < WT_SUPPORT_COMPATIBLE) {
360             error_setg(errp, "Background-snapshot is not compatible "
361                     "with guest memory configuration");
362             return false;
363         }
364 
365         /*
366          * Check if there are any migration capabilities
367          * incompatible with 'background-snapshot'.
368          */
369         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
370             int incomp_cap = check_caps_background_snapshot.caps[idx];
371             if (new_caps[incomp_cap]) {
372                 error_setg(errp,
373                         "Background-snapshot is not compatible with %s",
374                         MigrationCapability_str(incomp_cap));
375                 return false;
376             }
377         }
378     }
379 
380 #ifdef CONFIG_LINUX
381     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
382         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
383          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
384          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
385          migrate_multifd_compression() ||
386          migrate_tls())) {
387         error_setg(errp,
388                    "Zero copy only available for non-compressed non-TLS multifd migration");
389         return false;
390     }
391 #else
392     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
393         error_setg(errp,
394                    "Zero copy currently only available on Linux");
395         return false;
396     }
397 #endif
398 
399     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
400         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
401             error_setg(errp, "Postcopy preempt requires postcopy-ram");
402             return false;
403         }
404 
405         /*
406          * Preempt mode requires urgent pages to be sent in separate
407          * channel, OTOH compression logic will disorder all pages into
408          * different compression channels, which is not compatible with the
409          * preempt assumptions on channel assignments.
410          */
411         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
412             error_setg(errp, "Postcopy preempt not compatible with compress");
413             return false;
414         }
415     }
416 
417     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
418         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
419             error_setg(errp, "Multifd is not compatible with compress");
420             return false;
421         }
422     }
423 
424     return true;
425 }
426 
427 bool migrate_cap_set(int cap, bool value, Error **errp)
428 {
429     MigrationState *s = migrate_get_current();
430     bool new_caps[MIGRATION_CAPABILITY__MAX];
431 
432     if (migration_is_running(s->state)) {
433         error_setg(errp, QERR_MIGRATION_ACTIVE);
434         return false;
435     }
436 
437     memcpy(new_caps, s->capabilities, sizeof(new_caps));
438     new_caps[cap] = value;
439 
440     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
441         return false;
442     }
443     s->capabilities[cap] = value;
444     return true;
445 }
446 
447 MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
448 {
449     MigrationCapabilityStatusList *head = NULL, **tail = &head;
450     MigrationCapabilityStatus *caps;
451     MigrationState *s = migrate_get_current();
452     int i;
453 
454     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
455 #ifndef CONFIG_LIVE_BLOCK_MIGRATION
456         if (i == MIGRATION_CAPABILITY_BLOCK) {
457             continue;
458         }
459 #endif
460         caps = g_malloc0(sizeof(*caps));
461         caps->capability = i;
462         caps->state = s->capabilities[i];
463         QAPI_LIST_APPEND(tail, caps);
464     }
465 
466     return head;
467 }
468 
469 void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
470                                   Error **errp)
471 {
472     MigrationState *s = migrate_get_current();
473     MigrationCapabilityStatusList *cap;
474     bool new_caps[MIGRATION_CAPABILITY__MAX];
475 
476     if (migration_is_running(s->state)) {
477         error_setg(errp, QERR_MIGRATION_ACTIVE);
478         return;
479     }
480 
481     memcpy(new_caps, s->capabilities, sizeof(new_caps));
482     for (cap = params; cap; cap = cap->next) {
483         new_caps[cap->value->capability] = cap->value->state;
484     }
485 
486     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
487         return;
488     }
489 
490     for (cap = params; cap; cap = cap->next) {
491         s->capabilities[cap->value->capability] = cap->value->state;
492     }
493 }
494 
495 /* parameters */
496 
497 bool migrate_block_incremental(void)
498 {
499     MigrationState *s;
500 
501     s = migrate_get_current();
502 
503     return s->parameters.block_incremental;
504 }
505 
506 uint32_t migrate_checkpoint_delay(void)
507 {
508     MigrationState *s;
509 
510     s = migrate_get_current();
511 
512     return s->parameters.x_checkpoint_delay;
513 }
514 
515 int migrate_compress_level(void)
516 {
517     MigrationState *s;
518 
519     s = migrate_get_current();
520 
521     return s->parameters.compress_level;
522 }
523 
524 int migrate_compress_threads(void)
525 {
526     MigrationState *s;
527 
528     s = migrate_get_current();
529 
530     return s->parameters.compress_threads;
531 }
532 
533 int migrate_compress_wait_thread(void)
534 {
535     MigrationState *s;
536 
537     s = migrate_get_current();
538 
539     return s->parameters.compress_wait_thread;
540 }
541 
542 uint8_t migrate_cpu_throttle_increment(void)
543 {
544     MigrationState *s;
545 
546     s = migrate_get_current();
547 
548     return s->parameters.cpu_throttle_increment;
549 }
550 
551 uint8_t migrate_cpu_throttle_initial(void)
552 {
553     MigrationState *s;
554 
555     s = migrate_get_current();
556 
557     return s->parameters.cpu_throttle_initial;
558 }
559 
560 bool migrate_cpu_throttle_tailslow(void)
561 {
562     MigrationState *s;
563 
564     s = migrate_get_current();
565 
566     return s->parameters.cpu_throttle_tailslow;
567 }
568 
569 int migrate_decompress_threads(void)
570 {
571     MigrationState *s;
572 
573     s = migrate_get_current();
574 
575     return s->parameters.decompress_threads;
576 }
577 
578 uint8_t migrate_max_cpu_throttle(void)
579 {
580     MigrationState *s;
581 
582     s = migrate_get_current();
583 
584     return s->parameters.max_cpu_throttle;
585 }
586 
587 uint64_t migrate_max_bandwidth(void)
588 {
589     MigrationState *s;
590 
591     s = migrate_get_current();
592 
593     return s->parameters.max_bandwidth;
594 }
595 
596 int64_t migrate_max_postcopy_bandwidth(void)
597 {
598     MigrationState *s;
599 
600     s = migrate_get_current();
601 
602     return s->parameters.max_postcopy_bandwidth;
603 }
604 
605 int migrate_multifd_channels(void)
606 {
607     MigrationState *s;
608 
609     s = migrate_get_current();
610 
611     return s->parameters.multifd_channels;
612 }
613 
614 MultiFDCompression migrate_multifd_compression(void)
615 {
616     MigrationState *s;
617 
618     s = migrate_get_current();
619 
620     assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
621     return s->parameters.multifd_compression;
622 }
623 
624 int migrate_multifd_zlib_level(void)
625 {
626     MigrationState *s;
627 
628     s = migrate_get_current();
629 
630     return s->parameters.multifd_zlib_level;
631 }
632 
633 int migrate_multifd_zstd_level(void)
634 {
635     MigrationState *s;
636 
637     s = migrate_get_current();
638 
639     return s->parameters.multifd_zstd_level;
640 }
641 
642 uint8_t migrate_throttle_trigger_threshold(void)
643 {
644     MigrationState *s;
645 
646     s = migrate_get_current();
647 
648     return s->parameters.throttle_trigger_threshold;
649 }
650 
651 uint64_t migrate_xbzrle_cache_size(void)
652 {
653     MigrationState *s;
654 
655     s = migrate_get_current();
656 
657     return s->parameters.xbzrle_cache_size;
658 }
659 
660 /* parameters helpers */
661 
662 AnnounceParameters *migrate_announce_params(void)
663 {
664     static AnnounceParameters ap;
665 
666     MigrationState *s = migrate_get_current();
667 
668     ap.initial = s->parameters.announce_initial;
669     ap.max = s->parameters.announce_max;
670     ap.rounds = s->parameters.announce_rounds;
671     ap.step = s->parameters.announce_step;
672 
673     return &ap;
674 }
675 
676 MigrationParameters *qmp_query_migrate_parameters(Error **errp)
677 {
678     MigrationParameters *params;
679     MigrationState *s = migrate_get_current();
680 
681     /* TODO use QAPI_CLONE() instead of duplicating it inline */
682     params = g_malloc0(sizeof(*params));
683     params->has_compress_level = true;
684     params->compress_level = s->parameters.compress_level;
685     params->has_compress_threads = true;
686     params->compress_threads = s->parameters.compress_threads;
687     params->has_compress_wait_thread = true;
688     params->compress_wait_thread = s->parameters.compress_wait_thread;
689     params->has_decompress_threads = true;
690     params->decompress_threads = s->parameters.decompress_threads;
691     params->has_throttle_trigger_threshold = true;
692     params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
693     params->has_cpu_throttle_initial = true;
694     params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
695     params->has_cpu_throttle_increment = true;
696     params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
697     params->has_cpu_throttle_tailslow = true;
698     params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
699     params->tls_creds = g_strdup(s->parameters.tls_creds);
700     params->tls_hostname = g_strdup(s->parameters.tls_hostname);
701     params->tls_authz = g_strdup(s->parameters.tls_authz ?
702                                  s->parameters.tls_authz : "");
703     params->has_max_bandwidth = true;
704     params->max_bandwidth = s->parameters.max_bandwidth;
705     params->has_downtime_limit = true;
706     params->downtime_limit = s->parameters.downtime_limit;
707     params->has_x_checkpoint_delay = true;
708     params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
709     params->has_block_incremental = true;
710     params->block_incremental = s->parameters.block_incremental;
711     params->has_multifd_channels = true;
712     params->multifd_channels = s->parameters.multifd_channels;
713     params->has_multifd_compression = true;
714     params->multifd_compression = s->parameters.multifd_compression;
715     params->has_multifd_zlib_level = true;
716     params->multifd_zlib_level = s->parameters.multifd_zlib_level;
717     params->has_multifd_zstd_level = true;
718     params->multifd_zstd_level = s->parameters.multifd_zstd_level;
719     params->has_xbzrle_cache_size = true;
720     params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
721     params->has_max_postcopy_bandwidth = true;
722     params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
723     params->has_max_cpu_throttle = true;
724     params->max_cpu_throttle = s->parameters.max_cpu_throttle;
725     params->has_announce_initial = true;
726     params->announce_initial = s->parameters.announce_initial;
727     params->has_announce_max = true;
728     params->announce_max = s->parameters.announce_max;
729     params->has_announce_rounds = true;
730     params->announce_rounds = s->parameters.announce_rounds;
731     params->has_announce_step = true;
732     params->announce_step = s->parameters.announce_step;
733 
734     if (s->parameters.has_block_bitmap_mapping) {
735         params->has_block_bitmap_mapping = true;
736         params->block_bitmap_mapping =
737             QAPI_CLONE(BitmapMigrationNodeAliasList,
738                        s->parameters.block_bitmap_mapping);
739     }
740 
741     return params;
742 }
743 
744 void migrate_params_init(MigrationParameters *params)
745 {
746     params->tls_hostname = g_strdup("");
747     params->tls_creds = g_strdup("");
748 
749     /* Set has_* up only for parameter checks */
750     params->has_compress_level = true;
751     params->has_compress_threads = true;
752     params->has_compress_wait_thread = true;
753     params->has_decompress_threads = true;
754     params->has_throttle_trigger_threshold = true;
755     params->has_cpu_throttle_initial = true;
756     params->has_cpu_throttle_increment = true;
757     params->has_cpu_throttle_tailslow = true;
758     params->has_max_bandwidth = true;
759     params->has_downtime_limit = true;
760     params->has_x_checkpoint_delay = true;
761     params->has_block_incremental = true;
762     params->has_multifd_channels = true;
763     params->has_multifd_compression = true;
764     params->has_multifd_zlib_level = true;
765     params->has_multifd_zstd_level = true;
766     params->has_xbzrle_cache_size = true;
767     params->has_max_postcopy_bandwidth = true;
768     params->has_max_cpu_throttle = true;
769     params->has_announce_initial = true;
770     params->has_announce_max = true;
771     params->has_announce_rounds = true;
772     params->has_announce_step = true;
773 }
774 
775 /*
776  * Check whether the parameters are valid. Error will be put into errp
777  * (if provided). Return true if valid, otherwise false.
778  */
779 bool migrate_params_check(MigrationParameters *params, Error **errp)
780 {
781     if (params->has_compress_level &&
782         (params->compress_level > 9)) {
783         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
784                    "a value between 0 and 9");
785         return false;
786     }
787 
788     if (params->has_compress_threads && (params->compress_threads < 1)) {
789         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
790                    "compress_threads",
791                    "a value between 1 and 255");
792         return false;
793     }
794 
795     if (params->has_decompress_threads && (params->decompress_threads < 1)) {
796         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
797                    "decompress_threads",
798                    "a value between 1 and 255");
799         return false;
800     }
801 
802     if (params->has_throttle_trigger_threshold &&
803         (params->throttle_trigger_threshold < 1 ||
804          params->throttle_trigger_threshold > 100)) {
805         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
806                    "throttle_trigger_threshold",
807                    "an integer in the range of 1 to 100");
808         return false;
809     }
810 
811     if (params->has_cpu_throttle_initial &&
812         (params->cpu_throttle_initial < 1 ||
813          params->cpu_throttle_initial > 99)) {
814         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
815                    "cpu_throttle_initial",
816                    "an integer in the range of 1 to 99");
817         return false;
818     }
819 
820     if (params->has_cpu_throttle_increment &&
821         (params->cpu_throttle_increment < 1 ||
822          params->cpu_throttle_increment > 99)) {
823         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
824                    "cpu_throttle_increment",
825                    "an integer in the range of 1 to 99");
826         return false;
827     }
828 
829     if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) {
830         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
831                    "max_bandwidth",
832                    "an integer in the range of 0 to "stringify(SIZE_MAX)
833                    " bytes/second");
834         return false;
835     }
836 
837     if (params->has_downtime_limit &&
838         (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) {
839         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
840                    "downtime_limit",
841                    "an integer in the range of 0 to "
842                     stringify(MAX_MIGRATE_DOWNTIME)" ms");
843         return false;
844     }
845 
846     /* x_checkpoint_delay is now always positive */
847 
848     if (params->has_multifd_channels && (params->multifd_channels < 1)) {
849         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
850                    "multifd_channels",
851                    "a value between 1 and 255");
852         return false;
853     }
854 
855     if (params->has_multifd_zlib_level &&
856         (params->multifd_zlib_level > 9)) {
857         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zlib_level",
858                    "a value between 0 and 9");
859         return false;
860     }
861 
862     if (params->has_multifd_zstd_level &&
863         (params->multifd_zstd_level > 20)) {
864         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level",
865                    "a value between 0 and 20");
866         return false;
867     }
868 
869     if (params->has_xbzrle_cache_size &&
870         (params->xbzrle_cache_size < qemu_target_page_size() ||
871          !is_power_of_2(params->xbzrle_cache_size))) {
872         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
873                    "xbzrle_cache_size",
874                    "a power of two no less than the target page size");
875         return false;
876     }
877 
878     if (params->has_max_cpu_throttle &&
879         (params->max_cpu_throttle < params->cpu_throttle_initial ||
880          params->max_cpu_throttle > 99)) {
881         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
882                    "max_cpu_throttle",
883                    "an integer in the range of cpu_throttle_initial to 99");
884         return false;
885     }
886 
887     if (params->has_announce_initial &&
888         params->announce_initial > 100000) {
889         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
890                    "announce_initial",
891                    "a value between 0 and 100000");
892         return false;
893     }
894     if (params->has_announce_max &&
895         params->announce_max > 100000) {
896         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
897                    "announce_max",
898                    "a value between 0 and 100000");
899        return false;
900     }
901     if (params->has_announce_rounds &&
902         params->announce_rounds > 1000) {
903         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
904                    "announce_rounds",
905                    "a value between 0 and 1000");
906        return false;
907     }
908     if (params->has_announce_step &&
909         (params->announce_step < 1 ||
910         params->announce_step > 10000)) {
911         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
912                    "announce_step",
913                    "a value between 0 and 10000");
914        return false;
915     }
916 
917     if (params->has_block_bitmap_mapping &&
918         !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) {
919         error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: ");
920         return false;
921     }
922 
923 #ifdef CONFIG_LINUX
924     if (migrate_zero_copy_send() &&
925         ((params->has_multifd_compression && params->multifd_compression) ||
926          (params->tls_creds && *params->tls_creds))) {
927         error_setg(errp,
928                    "Zero copy only available for non-compressed non-TLS multifd migration");
929         return false;
930     }
931 #endif
932 
933     return true;
934 }
935 
936 static void migrate_params_test_apply(MigrateSetParameters *params,
937                                       MigrationParameters *dest)
938 {
939     *dest = migrate_get_current()->parameters;
940 
941     /* TODO use QAPI_CLONE() instead of duplicating it inline */
942 
943     if (params->has_compress_level) {
944         dest->compress_level = params->compress_level;
945     }
946 
947     if (params->has_compress_threads) {
948         dest->compress_threads = params->compress_threads;
949     }
950 
951     if (params->has_compress_wait_thread) {
952         dest->compress_wait_thread = params->compress_wait_thread;
953     }
954 
955     if (params->has_decompress_threads) {
956         dest->decompress_threads = params->decompress_threads;
957     }
958 
959     if (params->has_throttle_trigger_threshold) {
960         dest->throttle_trigger_threshold = params->throttle_trigger_threshold;
961     }
962 
963     if (params->has_cpu_throttle_initial) {
964         dest->cpu_throttle_initial = params->cpu_throttle_initial;
965     }
966 
967     if (params->has_cpu_throttle_increment) {
968         dest->cpu_throttle_increment = params->cpu_throttle_increment;
969     }
970 
971     if (params->has_cpu_throttle_tailslow) {
972         dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow;
973     }
974 
975     if (params->tls_creds) {
976         assert(params->tls_creds->type == QTYPE_QSTRING);
977         dest->tls_creds = params->tls_creds->u.s;
978     }
979 
980     if (params->tls_hostname) {
981         assert(params->tls_hostname->type == QTYPE_QSTRING);
982         dest->tls_hostname = params->tls_hostname->u.s;
983     }
984 
985     if (params->has_max_bandwidth) {
986         dest->max_bandwidth = params->max_bandwidth;
987     }
988 
989     if (params->has_downtime_limit) {
990         dest->downtime_limit = params->downtime_limit;
991     }
992 
993     if (params->has_x_checkpoint_delay) {
994         dest->x_checkpoint_delay = params->x_checkpoint_delay;
995     }
996 
997     if (params->has_block_incremental) {
998         dest->block_incremental = params->block_incremental;
999     }
1000     if (params->has_multifd_channels) {
1001         dest->multifd_channels = params->multifd_channels;
1002     }
1003     if (params->has_multifd_compression) {
1004         dest->multifd_compression = params->multifd_compression;
1005     }
1006     if (params->has_xbzrle_cache_size) {
1007         dest->xbzrle_cache_size = params->xbzrle_cache_size;
1008     }
1009     if (params->has_max_postcopy_bandwidth) {
1010         dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1011     }
1012     if (params->has_max_cpu_throttle) {
1013         dest->max_cpu_throttle = params->max_cpu_throttle;
1014     }
1015     if (params->has_announce_initial) {
1016         dest->announce_initial = params->announce_initial;
1017     }
1018     if (params->has_announce_max) {
1019         dest->announce_max = params->announce_max;
1020     }
1021     if (params->has_announce_rounds) {
1022         dest->announce_rounds = params->announce_rounds;
1023     }
1024     if (params->has_announce_step) {
1025         dest->announce_step = params->announce_step;
1026     }
1027 
1028     if (params->has_block_bitmap_mapping) {
1029         dest->has_block_bitmap_mapping = true;
1030         dest->block_bitmap_mapping = params->block_bitmap_mapping;
1031     }
1032 }
1033 
1034 static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
1035 {
1036     MigrationState *s = migrate_get_current();
1037 
1038     /* TODO use QAPI_CLONE() instead of duplicating it inline */
1039 
1040     if (params->has_compress_level) {
1041         s->parameters.compress_level = params->compress_level;
1042     }
1043 
1044     if (params->has_compress_threads) {
1045         s->parameters.compress_threads = params->compress_threads;
1046     }
1047 
1048     if (params->has_compress_wait_thread) {
1049         s->parameters.compress_wait_thread = params->compress_wait_thread;
1050     }
1051 
1052     if (params->has_decompress_threads) {
1053         s->parameters.decompress_threads = params->decompress_threads;
1054     }
1055 
1056     if (params->has_throttle_trigger_threshold) {
1057         s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold;
1058     }
1059 
1060     if (params->has_cpu_throttle_initial) {
1061         s->parameters.cpu_throttle_initial = params->cpu_throttle_initial;
1062     }
1063 
1064     if (params->has_cpu_throttle_increment) {
1065         s->parameters.cpu_throttle_increment = params->cpu_throttle_increment;
1066     }
1067 
1068     if (params->has_cpu_throttle_tailslow) {
1069         s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow;
1070     }
1071 
1072     if (params->tls_creds) {
1073         g_free(s->parameters.tls_creds);
1074         assert(params->tls_creds->type == QTYPE_QSTRING);
1075         s->parameters.tls_creds = g_strdup(params->tls_creds->u.s);
1076     }
1077 
1078     if (params->tls_hostname) {
1079         g_free(s->parameters.tls_hostname);
1080         assert(params->tls_hostname->type == QTYPE_QSTRING);
1081         s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s);
1082     }
1083 
1084     if (params->tls_authz) {
1085         g_free(s->parameters.tls_authz);
1086         assert(params->tls_authz->type == QTYPE_QSTRING);
1087         s->parameters.tls_authz = g_strdup(params->tls_authz->u.s);
1088     }
1089 
1090     if (params->has_max_bandwidth) {
1091         s->parameters.max_bandwidth = params->max_bandwidth;
1092         if (s->to_dst_file && !migration_in_postcopy()) {
1093             qemu_file_set_rate_limit(s->to_dst_file,
1094                                 s->parameters.max_bandwidth / XFER_LIMIT_RATIO);
1095         }
1096     }
1097 
1098     if (params->has_downtime_limit) {
1099         s->parameters.downtime_limit = params->downtime_limit;
1100     }
1101 
1102     if (params->has_x_checkpoint_delay) {
1103         s->parameters.x_checkpoint_delay = params->x_checkpoint_delay;
1104         if (migration_in_colo_state()) {
1105             colo_checkpoint_notify(s);
1106         }
1107     }
1108 
1109     if (params->has_block_incremental) {
1110         s->parameters.block_incremental = params->block_incremental;
1111     }
1112     if (params->has_multifd_channels) {
1113         s->parameters.multifd_channels = params->multifd_channels;
1114     }
1115     if (params->has_multifd_compression) {
1116         s->parameters.multifd_compression = params->multifd_compression;
1117     }
1118     if (params->has_xbzrle_cache_size) {
1119         s->parameters.xbzrle_cache_size = params->xbzrle_cache_size;
1120         xbzrle_cache_resize(params->xbzrle_cache_size, errp);
1121     }
1122     if (params->has_max_postcopy_bandwidth) {
1123         s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1124         if (s->to_dst_file && migration_in_postcopy()) {
1125             qemu_file_set_rate_limit(s->to_dst_file,
1126                     s->parameters.max_postcopy_bandwidth / XFER_LIMIT_RATIO);
1127         }
1128     }
1129     if (params->has_max_cpu_throttle) {
1130         s->parameters.max_cpu_throttle = params->max_cpu_throttle;
1131     }
1132     if (params->has_announce_initial) {
1133         s->parameters.announce_initial = params->announce_initial;
1134     }
1135     if (params->has_announce_max) {
1136         s->parameters.announce_max = params->announce_max;
1137     }
1138     if (params->has_announce_rounds) {
1139         s->parameters.announce_rounds = params->announce_rounds;
1140     }
1141     if (params->has_announce_step) {
1142         s->parameters.announce_step = params->announce_step;
1143     }
1144 
1145     if (params->has_block_bitmap_mapping) {
1146         qapi_free_BitmapMigrationNodeAliasList(
1147             s->parameters.block_bitmap_mapping);
1148 
1149         s->parameters.has_block_bitmap_mapping = true;
1150         s->parameters.block_bitmap_mapping =
1151             QAPI_CLONE(BitmapMigrationNodeAliasList,
1152                        params->block_bitmap_mapping);
1153     }
1154 }
1155 
1156 void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
1157 {
1158     MigrationParameters tmp;
1159 
1160     /* TODO Rewrite "" to null instead */
1161     if (params->tls_creds
1162         && params->tls_creds->type == QTYPE_QNULL) {
1163         qobject_unref(params->tls_creds->u.n);
1164         params->tls_creds->type = QTYPE_QSTRING;
1165         params->tls_creds->u.s = strdup("");
1166     }
1167     /* TODO Rewrite "" to null instead */
1168     if (params->tls_hostname
1169         && params->tls_hostname->type == QTYPE_QNULL) {
1170         qobject_unref(params->tls_hostname->u.n);
1171         params->tls_hostname->type = QTYPE_QSTRING;
1172         params->tls_hostname->u.s = strdup("");
1173     }
1174 
1175     migrate_params_test_apply(params, &tmp);
1176 
1177     if (!migrate_params_check(&tmp, errp)) {
1178         /* Invalid parameter */
1179         return;
1180     }
1181 
1182     migrate_params_apply(params, errp);
1183 }
1184