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