xref: /openbmc/qemu/migration/options.c (revision eef0bae3)
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 "qemu/error-report.h"
16 #include "exec/target_page.h"
17 #include "qapi/clone-visitor.h"
18 #include "qapi/error.h"
19 #include "qapi/qapi-commands-migration.h"
20 #include "qapi/qapi-visit-migration.h"
21 #include "qapi/qmp/qerror.h"
22 #include "qapi/qmp/qnull.h"
23 #include "sysemu/runstate.h"
24 #include "migration/colo.h"
25 #include "migration/misc.h"
26 #include "migration.h"
27 #include "migration-stats.h"
28 #include "qemu-file.h"
29 #include "ram.h"
30 #include "options.h"
31 #include "sysemu/kvm.h"
32 
33 /* Maximum migrate downtime set to 2000 seconds */
34 #define MAX_MIGRATE_DOWNTIME_SECONDS 2000
35 #define MAX_MIGRATE_DOWNTIME (MAX_MIGRATE_DOWNTIME_SECONDS * 1000)
36 
37 #define MAX_THROTTLE  (128 << 20)      /* Migration transfer speed throttling */
38 
39 /* Time in milliseconds we are allowed to stop the source,
40  * for sending the last part */
41 #define DEFAULT_MIGRATE_SET_DOWNTIME 300
42 
43 /* Default compression thread count */
44 #define DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT 8
45 /* Default decompression thread count, usually decompression is at
46  * least 4 times as fast as compression.*/
47 #define DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT 2
48 /*0: means nocompress, 1: best speed, ... 9: best compress ratio */
49 #define DEFAULT_MIGRATE_COMPRESS_LEVEL 1
50 /* Define default autoconverge cpu throttle migration parameters */
51 #define DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD 50
52 #define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20
53 #define DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT 10
54 #define DEFAULT_MIGRATE_MAX_CPU_THROTTLE 99
55 
56 /* Migration XBZRLE default cache size */
57 #define DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE (64 * 1024 * 1024)
58 
59 /* The delay time (in ms) between two COLO checkpoints */
60 #define DEFAULT_MIGRATE_X_CHECKPOINT_DELAY (200 * 100)
61 #define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2
62 #define DEFAULT_MIGRATE_MULTIFD_COMPRESSION MULTIFD_COMPRESSION_NONE
63 /* 0: means nocompress, 1: best speed, ... 9: best compress ratio */
64 #define DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL 1
65 /* 0: means nocompress, 1: best speed, ... 20: best compress ratio */
66 #define DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL 1
67 
68 /* Background transfer rate for postcopy, 0 means unlimited, note
69  * that page requests can still exceed this limit.
70  */
71 #define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0
72 
73 /*
74  * Parameters for self_announce_delay giving a stream of RARP/ARP
75  * packets after migration.
76  */
77 #define DEFAULT_MIGRATE_ANNOUNCE_INITIAL  50
78 #define DEFAULT_MIGRATE_ANNOUNCE_MAX     550
79 #define DEFAULT_MIGRATE_ANNOUNCE_ROUNDS    5
80 #define DEFAULT_MIGRATE_ANNOUNCE_STEP    100
81 
82 #define DEFINE_PROP_MIG_CAP(name, x)             \
83     DEFINE_PROP_BOOL(name, MigrationState, capabilities[x], false)
84 
85 #define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD     1000    /* milliseconds */
86 #define DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT            1       /* MB/s */
87 
88 Property migration_properties[] = {
89     DEFINE_PROP_BOOL("store-global-state", MigrationState,
90                      store_global_state, true),
91     DEFINE_PROP_BOOL("send-configuration", MigrationState,
92                      send_configuration, true),
93     DEFINE_PROP_BOOL("send-section-footer", MigrationState,
94                      send_section_footer, true),
95     DEFINE_PROP_BOOL("decompress-error-check", MigrationState,
96                       decompress_error_check, true),
97     DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState,
98                       multifd_flush_after_each_section, false),
99     DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState,
100                       clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT),
101     DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState,
102                      preempt_pre_7_2, false),
103 
104     /* Migration parameters */
105     DEFINE_PROP_UINT8("x-compress-level", MigrationState,
106                       parameters.compress_level,
107                       DEFAULT_MIGRATE_COMPRESS_LEVEL),
108     DEFINE_PROP_UINT8("x-compress-threads", MigrationState,
109                       parameters.compress_threads,
110                       DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT),
111     DEFINE_PROP_BOOL("x-compress-wait-thread", MigrationState,
112                       parameters.compress_wait_thread, true),
113     DEFINE_PROP_UINT8("x-decompress-threads", MigrationState,
114                       parameters.decompress_threads,
115                       DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT),
116     DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState,
117                       parameters.throttle_trigger_threshold,
118                       DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD),
119     DEFINE_PROP_UINT8("x-cpu-throttle-initial", MigrationState,
120                       parameters.cpu_throttle_initial,
121                       DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL),
122     DEFINE_PROP_UINT8("x-cpu-throttle-increment", MigrationState,
123                       parameters.cpu_throttle_increment,
124                       DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT),
125     DEFINE_PROP_BOOL("x-cpu-throttle-tailslow", MigrationState,
126                       parameters.cpu_throttle_tailslow, false),
127     DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState,
128                       parameters.max_bandwidth, MAX_THROTTLE),
129     DEFINE_PROP_SIZE("avail-switchover-bandwidth", MigrationState,
130                       parameters.avail_switchover_bandwidth, 0),
131     DEFINE_PROP_UINT64("x-downtime-limit", MigrationState,
132                       parameters.downtime_limit,
133                       DEFAULT_MIGRATE_SET_DOWNTIME),
134     DEFINE_PROP_UINT32("x-checkpoint-delay", MigrationState,
135                       parameters.x_checkpoint_delay,
136                       DEFAULT_MIGRATE_X_CHECKPOINT_DELAY),
137     DEFINE_PROP_UINT8("multifd-channels", MigrationState,
138                       parameters.multifd_channels,
139                       DEFAULT_MIGRATE_MULTIFD_CHANNELS),
140     DEFINE_PROP_MULTIFD_COMPRESSION("multifd-compression", MigrationState,
141                       parameters.multifd_compression,
142                       DEFAULT_MIGRATE_MULTIFD_COMPRESSION),
143     DEFINE_PROP_UINT8("multifd-zlib-level", MigrationState,
144                       parameters.multifd_zlib_level,
145                       DEFAULT_MIGRATE_MULTIFD_ZLIB_LEVEL),
146     DEFINE_PROP_UINT8("multifd-zstd-level", MigrationState,
147                       parameters.multifd_zstd_level,
148                       DEFAULT_MIGRATE_MULTIFD_ZSTD_LEVEL),
149     DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState,
150                       parameters.xbzrle_cache_size,
151                       DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE),
152     DEFINE_PROP_SIZE("max-postcopy-bandwidth", MigrationState,
153                       parameters.max_postcopy_bandwidth,
154                       DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH),
155     DEFINE_PROP_UINT8("max-cpu-throttle", MigrationState,
156                       parameters.max_cpu_throttle,
157                       DEFAULT_MIGRATE_MAX_CPU_THROTTLE),
158     DEFINE_PROP_SIZE("announce-initial", MigrationState,
159                       parameters.announce_initial,
160                       DEFAULT_MIGRATE_ANNOUNCE_INITIAL),
161     DEFINE_PROP_SIZE("announce-max", MigrationState,
162                       parameters.announce_max,
163                       DEFAULT_MIGRATE_ANNOUNCE_MAX),
164     DEFINE_PROP_SIZE("announce-rounds", MigrationState,
165                       parameters.announce_rounds,
166                       DEFAULT_MIGRATE_ANNOUNCE_ROUNDS),
167     DEFINE_PROP_SIZE("announce-step", MigrationState,
168                       parameters.announce_step,
169                       DEFAULT_MIGRATE_ANNOUNCE_STEP),
170     DEFINE_PROP_STRING("tls-creds", MigrationState, parameters.tls_creds),
171     DEFINE_PROP_STRING("tls-hostname", MigrationState, parameters.tls_hostname),
172     DEFINE_PROP_STRING("tls-authz", MigrationState, parameters.tls_authz),
173     DEFINE_PROP_UINT64("x-vcpu-dirty-limit-period", MigrationState,
174                        parameters.x_vcpu_dirty_limit_period,
175                        DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT_PERIOD),
176     DEFINE_PROP_UINT64("vcpu-dirty-limit", MigrationState,
177                        parameters.vcpu_dirty_limit,
178                        DEFAULT_MIGRATE_VCPU_DIRTY_LIMIT),
179     DEFINE_PROP_MIG_MODE("mode", MigrationState,
180                       parameters.mode,
181                       MIG_MODE_NORMAL),
182     DEFINE_PROP_ZERO_PAGE_DETECTION("zero-page-detection", MigrationState,
183                        parameters.zero_page_detection,
184                        ZERO_PAGE_DETECTION_MULTIFD),
185 
186     /* Migration capabilities */
187     DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
188     DEFINE_PROP_MIG_CAP("x-rdma-pin-all", MIGRATION_CAPABILITY_RDMA_PIN_ALL),
189     DEFINE_PROP_MIG_CAP("x-auto-converge", MIGRATION_CAPABILITY_AUTO_CONVERGE),
190     DEFINE_PROP_MIG_CAP("x-zero-blocks", MIGRATION_CAPABILITY_ZERO_BLOCKS),
191     DEFINE_PROP_MIG_CAP("x-compress", MIGRATION_CAPABILITY_COMPRESS),
192     DEFINE_PROP_MIG_CAP("x-events", MIGRATION_CAPABILITY_EVENTS),
193     DEFINE_PROP_MIG_CAP("x-postcopy-ram", MIGRATION_CAPABILITY_POSTCOPY_RAM),
194     DEFINE_PROP_MIG_CAP("x-postcopy-preempt",
195                         MIGRATION_CAPABILITY_POSTCOPY_PREEMPT),
196     DEFINE_PROP_MIG_CAP("x-colo", MIGRATION_CAPABILITY_X_COLO),
197     DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM),
198     DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH),
199     DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD),
200     DEFINE_PROP_MIG_CAP("x-background-snapshot",
201             MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT),
202 #ifdef CONFIG_LINUX
203     DEFINE_PROP_MIG_CAP("x-zero-copy-send",
204             MIGRATION_CAPABILITY_ZERO_COPY_SEND),
205 #endif
206     DEFINE_PROP_MIG_CAP("x-switchover-ack",
207                         MIGRATION_CAPABILITY_SWITCHOVER_ACK),
208     DEFINE_PROP_MIG_CAP("x-dirty-limit", MIGRATION_CAPABILITY_DIRTY_LIMIT),
209     DEFINE_PROP_MIG_CAP("mapped-ram", MIGRATION_CAPABILITY_MAPPED_RAM),
210     DEFINE_PROP_END_OF_LIST(),
211 };
212 
213 bool migrate_auto_converge(void)
214 {
215     MigrationState *s = migrate_get_current();
216 
217     return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
218 }
219 
220 bool migrate_background_snapshot(void)
221 {
222     MigrationState *s = migrate_get_current();
223 
224     return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
225 }
226 
227 bool migrate_colo(void)
228 {
229     MigrationState *s = migrate_get_current();
230 
231     return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
232 }
233 
234 bool migrate_compress(void)
235 {
236     MigrationState *s = migrate_get_current();
237 
238     return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
239 }
240 
241 bool migrate_dirty_bitmaps(void)
242 {
243     MigrationState *s = migrate_get_current();
244 
245     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
246 }
247 
248 bool migrate_dirty_limit(void)
249 {
250     MigrationState *s = migrate_get_current();
251 
252     return s->capabilities[MIGRATION_CAPABILITY_DIRTY_LIMIT];
253 }
254 
255 bool migrate_events(void)
256 {
257     MigrationState *s = migrate_get_current();
258 
259     return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
260 }
261 
262 bool migrate_mapped_ram(void)
263 {
264     MigrationState *s = migrate_get_current();
265 
266     return s->capabilities[MIGRATION_CAPABILITY_MAPPED_RAM];
267 }
268 
269 bool migrate_ignore_shared(void)
270 {
271     MigrationState *s = migrate_get_current();
272 
273     return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
274 }
275 
276 bool migrate_late_block_activate(void)
277 {
278     MigrationState *s = migrate_get_current();
279 
280     return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
281 }
282 
283 bool migrate_multifd(void)
284 {
285     MigrationState *s = migrate_get_current();
286 
287     return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
288 }
289 
290 bool migrate_pause_before_switchover(void)
291 {
292     MigrationState *s = migrate_get_current();
293 
294     return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
295 }
296 
297 bool migrate_postcopy_blocktime(void)
298 {
299     MigrationState *s = migrate_get_current();
300 
301     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
302 }
303 
304 bool migrate_postcopy_preempt(void)
305 {
306     MigrationState *s = migrate_get_current();
307 
308     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
309 }
310 
311 bool migrate_postcopy_ram(void)
312 {
313     MigrationState *s = migrate_get_current();
314 
315     return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
316 }
317 
318 bool migrate_rdma_pin_all(void)
319 {
320     MigrationState *s = migrate_get_current();
321 
322     return s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
323 }
324 
325 bool migrate_release_ram(void)
326 {
327     MigrationState *s = migrate_get_current();
328 
329     return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
330 }
331 
332 bool migrate_return_path(void)
333 {
334     MigrationState *s = migrate_get_current();
335 
336     return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
337 }
338 
339 bool migrate_switchover_ack(void)
340 {
341     MigrationState *s = migrate_get_current();
342 
343     return s->capabilities[MIGRATION_CAPABILITY_SWITCHOVER_ACK];
344 }
345 
346 bool migrate_validate_uuid(void)
347 {
348     MigrationState *s = migrate_get_current();
349 
350     return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
351 }
352 
353 bool migrate_xbzrle(void)
354 {
355     MigrationState *s = migrate_get_current();
356 
357     return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
358 }
359 
360 bool migrate_zero_blocks(void)
361 {
362     MigrationState *s = migrate_get_current();
363 
364     return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
365 }
366 
367 bool migrate_zero_copy_send(void)
368 {
369     MigrationState *s = migrate_get_current();
370 
371     return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
372 }
373 
374 /* pseudo capabilities */
375 
376 bool migrate_multifd_flush_after_each_section(void)
377 {
378     MigrationState *s = migrate_get_current();
379 
380     return s->multifd_flush_after_each_section;
381 }
382 
383 bool migrate_postcopy(void)
384 {
385     return migrate_postcopy_ram() || migrate_dirty_bitmaps();
386 }
387 
388 bool migrate_rdma(void)
389 {
390     MigrationState *s = migrate_get_current();
391 
392     return s->rdma_migration;
393 }
394 
395 bool migrate_tls(void)
396 {
397     MigrationState *s = migrate_get_current();
398 
399     return s->parameters.tls_creds && *s->parameters.tls_creds;
400 }
401 
402 typedef enum WriteTrackingSupport {
403     WT_SUPPORT_UNKNOWN = 0,
404     WT_SUPPORT_ABSENT,
405     WT_SUPPORT_AVAILABLE,
406     WT_SUPPORT_COMPATIBLE
407 } WriteTrackingSupport;
408 
409 static
410 WriteTrackingSupport migrate_query_write_tracking(void)
411 {
412     /* Check if kernel supports required UFFD features */
413     if (!ram_write_tracking_available()) {
414         return WT_SUPPORT_ABSENT;
415     }
416     /*
417      * Check if current memory configuration is
418      * compatible with required UFFD features.
419      */
420     if (!ram_write_tracking_compatible()) {
421         return WT_SUPPORT_AVAILABLE;
422     }
423 
424     return WT_SUPPORT_COMPATIBLE;
425 }
426 
427 /* Migration capabilities set */
428 struct MigrateCapsSet {
429     int size;                       /* Capability set size */
430     MigrationCapability caps[];     /* Variadic array of capabilities */
431 };
432 typedef struct MigrateCapsSet MigrateCapsSet;
433 
434 /* Define and initialize MigrateCapsSet */
435 #define INITIALIZE_MIGRATE_CAPS_SET(_name, ...)   \
436     MigrateCapsSet _name = {    \
437         .size = sizeof((int []) { __VA_ARGS__ }) / sizeof(int), \
438         .caps = { __VA_ARGS__ } \
439     }
440 
441 /* Background-snapshot compatibility check list */
442 static const
443 INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
444     MIGRATION_CAPABILITY_POSTCOPY_RAM,
445     MIGRATION_CAPABILITY_DIRTY_BITMAPS,
446     MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME,
447     MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE,
448     MIGRATION_CAPABILITY_RETURN_PATH,
449     MIGRATION_CAPABILITY_MULTIFD,
450     MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER,
451     MIGRATION_CAPABILITY_AUTO_CONVERGE,
452     MIGRATION_CAPABILITY_RELEASE_RAM,
453     MIGRATION_CAPABILITY_RDMA_PIN_ALL,
454     MIGRATION_CAPABILITY_COMPRESS,
455     MIGRATION_CAPABILITY_XBZRLE,
456     MIGRATION_CAPABILITY_X_COLO,
457     MIGRATION_CAPABILITY_VALIDATE_UUID,
458     MIGRATION_CAPABILITY_ZERO_COPY_SEND);
459 
460 static bool migrate_incoming_started(void)
461 {
462     return !!migration_incoming_get_current()->transport_data;
463 }
464 
465 /**
466  * @migration_caps_check - check capability compatibility
467  *
468  * @old_caps: old capability list
469  * @new_caps: new capability list
470  * @errp: set *errp if the check failed, with reason
471  *
472  * Returns true if check passed, otherwise false.
473  */
474 bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
475 {
476     ERRP_GUARD();
477     MigrationIncomingState *mis = migration_incoming_get_current();
478 
479     if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
480         warn_report("old compression method is deprecated;"
481                     " use multifd compression methods instead");
482     }
483 
484 #ifndef CONFIG_REPLICATION
485     if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
486         error_setg(errp, "QEMU compiled without replication module"
487                    " can't enable COLO");
488         error_append_hint(errp, "Please enable replication before COLO.\n");
489         return false;
490     }
491 #endif
492 
493     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
494         /* This check is reasonably expensive, so only when it's being
495          * set the first time, also it's only the destination that needs
496          * special support.
497          */
498         if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
499             runstate_check(RUN_STATE_INMIGRATE) &&
500             !postcopy_ram_supported_by_host(mis, errp)) {
501             error_prepend(errp, "Postcopy is not supported: ");
502             return false;
503         }
504 
505         if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
506             error_setg(errp, "Postcopy is not compatible with ignore-shared");
507             return false;
508         }
509 
510         if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
511             error_setg(errp, "Postcopy is not yet compatible with multifd");
512             return false;
513         }
514     }
515 
516     if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
517         WriteTrackingSupport wt_support;
518         int idx;
519         /*
520          * Check if 'background-snapshot' capability is supported by
521          * host kernel and compatible with guest memory configuration.
522          */
523         wt_support = migrate_query_write_tracking();
524         if (wt_support < WT_SUPPORT_AVAILABLE) {
525             error_setg(errp, "Background-snapshot is not supported by host kernel");
526             return false;
527         }
528         if (wt_support < WT_SUPPORT_COMPATIBLE) {
529             error_setg(errp, "Background-snapshot is not compatible "
530                     "with guest memory configuration");
531             return false;
532         }
533 
534         /*
535          * Check if there are any migration capabilities
536          * incompatible with 'background-snapshot'.
537          */
538         for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
539             int incomp_cap = check_caps_background_snapshot.caps[idx];
540             if (new_caps[incomp_cap]) {
541                 error_setg(errp,
542                         "Background-snapshot is not compatible with %s",
543                         MigrationCapability_str(incomp_cap));
544                 return false;
545             }
546         }
547     }
548 
549 #ifdef CONFIG_LINUX
550     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
551         (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
552          new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
553          new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
554          migrate_multifd_compression() ||
555          migrate_tls())) {
556         error_setg(errp,
557                    "Zero copy only available for non-compressed non-TLS multifd migration");
558         return false;
559     }
560 #else
561     if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
562         error_setg(errp,
563                    "Zero copy currently only available on Linux");
564         return false;
565     }
566 #endif
567 
568     if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
569         if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
570             error_setg(errp, "Postcopy preempt requires postcopy-ram");
571             return false;
572         }
573 
574         /*
575          * Preempt mode requires urgent pages to be sent in separate
576          * channel, OTOH compression logic will disorder all pages into
577          * different compression channels, which is not compatible with the
578          * preempt assumptions on channel assignments.
579          */
580         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
581             error_setg(errp, "Postcopy preempt not compatible with compress");
582             return false;
583         }
584 
585         if (migrate_incoming_started()) {
586             error_setg(errp,
587                        "Postcopy preempt must be set before incoming starts");
588             return false;
589         }
590     }
591 
592     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
593         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
594             error_setg(errp, "Multifd is not compatible with compress");
595             return false;
596         }
597         if (migrate_incoming_started()) {
598             error_setg(errp, "Multifd must be set before incoming starts");
599             return false;
600         }
601     }
602 
603     if (new_caps[MIGRATION_CAPABILITY_SWITCHOVER_ACK]) {
604         if (!new_caps[MIGRATION_CAPABILITY_RETURN_PATH]) {
605             error_setg(errp, "Capability 'switchover-ack' requires capability "
606                              "'return-path'");
607             return false;
608         }
609     }
610     if (new_caps[MIGRATION_CAPABILITY_DIRTY_LIMIT]) {
611         if (new_caps[MIGRATION_CAPABILITY_AUTO_CONVERGE]) {
612             error_setg(errp, "dirty-limit conflicts with auto-converge"
613                        " either of then available currently");
614             return false;
615         }
616 
617         if (!kvm_enabled() || !kvm_dirty_ring_enabled()) {
618             error_setg(errp, "dirty-limit requires KVM with accelerator"
619                    " property 'dirty-ring-size' set");
620             return false;
621         }
622     }
623 
624     if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
625         if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
626             error_setg(errp, "Multifd is not compatible with xbzrle");
627             return false;
628         }
629     }
630 
631     if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
632         if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
633             error_setg(errp, "Compression is not compatible with xbzrle");
634             return false;
635         }
636     }
637 
638     if (new_caps[MIGRATION_CAPABILITY_MAPPED_RAM]) {
639         if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
640             error_setg(errp,
641                        "Mapped-ram migration is incompatible with xbzrle");
642             return false;
643         }
644 
645         if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
646             error_setg(errp,
647                        "Mapped-ram migration is incompatible with compression");
648             return false;
649         }
650 
651         if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
652             error_setg(errp,
653                        "Mapped-ram migration is incompatible with postcopy");
654             return false;
655         }
656     }
657 
658     return true;
659 }
660 
661 bool migrate_cap_set(int cap, bool value, Error **errp)
662 {
663     MigrationState *s = migrate_get_current();
664     bool new_caps[MIGRATION_CAPABILITY__MAX];
665 
666     if (migration_is_running()) {
667         error_setg(errp, "There's a migration process in progress");
668         return false;
669     }
670 
671     memcpy(new_caps, s->capabilities, sizeof(new_caps));
672     new_caps[cap] = value;
673 
674     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
675         return false;
676     }
677     s->capabilities[cap] = value;
678     return true;
679 }
680 
681 MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
682 {
683     MigrationCapabilityStatusList *head = NULL, **tail = &head;
684     MigrationCapabilityStatus *caps;
685     MigrationState *s = migrate_get_current();
686     int i;
687 
688     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
689         caps = g_malloc0(sizeof(*caps));
690         caps->capability = i;
691         caps->state = s->capabilities[i];
692         QAPI_LIST_APPEND(tail, caps);
693     }
694 
695     return head;
696 }
697 
698 void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
699                                   Error **errp)
700 {
701     MigrationState *s = migrate_get_current();
702     MigrationCapabilityStatusList *cap;
703     bool new_caps[MIGRATION_CAPABILITY__MAX];
704 
705     if (migration_is_running() || migration_in_colo_state()) {
706         error_setg(errp, "There's a migration process in progress");
707         return;
708     }
709 
710     memcpy(new_caps, s->capabilities, sizeof(new_caps));
711     for (cap = params; cap; cap = cap->next) {
712         new_caps[cap->value->capability] = cap->value->state;
713     }
714 
715     if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
716         return;
717     }
718 
719     for (cap = params; cap; cap = cap->next) {
720         s->capabilities[cap->value->capability] = cap->value->state;
721     }
722 }
723 
724 /* parameters */
725 
726 const BitmapMigrationNodeAliasList *migrate_block_bitmap_mapping(void)
727 {
728     MigrationState *s = migrate_get_current();
729 
730     return s->parameters.block_bitmap_mapping;
731 }
732 
733 bool migrate_has_block_bitmap_mapping(void)
734 {
735     MigrationState *s = migrate_get_current();
736 
737     return s->parameters.has_block_bitmap_mapping;
738 }
739 
740 uint32_t migrate_checkpoint_delay(void)
741 {
742     MigrationState *s = migrate_get_current();
743 
744     return s->parameters.x_checkpoint_delay;
745 }
746 
747 int migrate_compress_level(void)
748 {
749     MigrationState *s = migrate_get_current();
750 
751     return s->parameters.compress_level;
752 }
753 
754 int migrate_compress_threads(void)
755 {
756     MigrationState *s = migrate_get_current();
757 
758     return s->parameters.compress_threads;
759 }
760 
761 int migrate_compress_wait_thread(void)
762 {
763     MigrationState *s = migrate_get_current();
764 
765     return s->parameters.compress_wait_thread;
766 }
767 
768 uint8_t migrate_cpu_throttle_increment(void)
769 {
770     MigrationState *s = migrate_get_current();
771 
772     return s->parameters.cpu_throttle_increment;
773 }
774 
775 uint8_t migrate_cpu_throttle_initial(void)
776 {
777     MigrationState *s = migrate_get_current();
778 
779     return s->parameters.cpu_throttle_initial;
780 }
781 
782 bool migrate_cpu_throttle_tailslow(void)
783 {
784     MigrationState *s = migrate_get_current();
785 
786     return s->parameters.cpu_throttle_tailslow;
787 }
788 
789 int migrate_decompress_threads(void)
790 {
791     MigrationState *s = migrate_get_current();
792 
793     return s->parameters.decompress_threads;
794 }
795 
796 uint64_t migrate_downtime_limit(void)
797 {
798     MigrationState *s = migrate_get_current();
799 
800     return s->parameters.downtime_limit;
801 }
802 
803 uint8_t migrate_max_cpu_throttle(void)
804 {
805     MigrationState *s = migrate_get_current();
806 
807     return s->parameters.max_cpu_throttle;
808 }
809 
810 uint64_t migrate_max_bandwidth(void)
811 {
812     MigrationState *s = migrate_get_current();
813 
814     return s->parameters.max_bandwidth;
815 }
816 
817 uint64_t migrate_avail_switchover_bandwidth(void)
818 {
819     MigrationState *s = migrate_get_current();
820 
821     return s->parameters.avail_switchover_bandwidth;
822 }
823 
824 uint64_t migrate_max_postcopy_bandwidth(void)
825 {
826     MigrationState *s = migrate_get_current();
827 
828     return s->parameters.max_postcopy_bandwidth;
829 }
830 
831 MigMode migrate_mode(void)
832 {
833     MigrationState *s = migrate_get_current();
834     MigMode mode = s->parameters.mode;
835 
836     assert(mode >= 0 && mode < MIG_MODE__MAX);
837     return mode;
838 }
839 
840 int migrate_multifd_channels(void)
841 {
842     MigrationState *s = migrate_get_current();
843 
844     return s->parameters.multifd_channels;
845 }
846 
847 MultiFDCompression migrate_multifd_compression(void)
848 {
849     MigrationState *s = migrate_get_current();
850 
851     assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX);
852     return s->parameters.multifd_compression;
853 }
854 
855 int migrate_multifd_zlib_level(void)
856 {
857     MigrationState *s = migrate_get_current();
858 
859     return s->parameters.multifd_zlib_level;
860 }
861 
862 int migrate_multifd_zstd_level(void)
863 {
864     MigrationState *s = migrate_get_current();
865 
866     return s->parameters.multifd_zstd_level;
867 }
868 
869 uint8_t migrate_throttle_trigger_threshold(void)
870 {
871     MigrationState *s = migrate_get_current();
872 
873     return s->parameters.throttle_trigger_threshold;
874 }
875 
876 const char *migrate_tls_authz(void)
877 {
878     MigrationState *s = migrate_get_current();
879 
880     return s->parameters.tls_authz;
881 }
882 
883 const char *migrate_tls_creds(void)
884 {
885     MigrationState *s = migrate_get_current();
886 
887     return s->parameters.tls_creds;
888 }
889 
890 const char *migrate_tls_hostname(void)
891 {
892     MigrationState *s = migrate_get_current();
893 
894     return s->parameters.tls_hostname;
895 }
896 
897 uint64_t migrate_vcpu_dirty_limit_period(void)
898 {
899     MigrationState *s = migrate_get_current();
900 
901     return s->parameters.x_vcpu_dirty_limit_period;
902 }
903 
904 uint64_t migrate_xbzrle_cache_size(void)
905 {
906     MigrationState *s = migrate_get_current();
907 
908     return s->parameters.xbzrle_cache_size;
909 }
910 
911 ZeroPageDetection migrate_zero_page_detection(void)
912 {
913     MigrationState *s = migrate_get_current();
914 
915     return s->parameters.zero_page_detection;
916 }
917 
918 /* parameters helpers */
919 
920 AnnounceParameters *migrate_announce_params(void)
921 {
922     static AnnounceParameters ap;
923 
924     MigrationState *s = migrate_get_current();
925 
926     ap.initial = s->parameters.announce_initial;
927     ap.max = s->parameters.announce_max;
928     ap.rounds = s->parameters.announce_rounds;
929     ap.step = s->parameters.announce_step;
930 
931     return &ap;
932 }
933 
934 MigrationParameters *qmp_query_migrate_parameters(Error **errp)
935 {
936     MigrationParameters *params;
937     MigrationState *s = migrate_get_current();
938 
939     /* TODO use QAPI_CLONE() instead of duplicating it inline */
940     params = g_malloc0(sizeof(*params));
941     params->has_compress_level = true;
942     params->compress_level = s->parameters.compress_level;
943     params->has_compress_threads = true;
944     params->compress_threads = s->parameters.compress_threads;
945     params->has_compress_wait_thread = true;
946     params->compress_wait_thread = s->parameters.compress_wait_thread;
947     params->has_decompress_threads = true;
948     params->decompress_threads = s->parameters.decompress_threads;
949     params->has_throttle_trigger_threshold = true;
950     params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
951     params->has_cpu_throttle_initial = true;
952     params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
953     params->has_cpu_throttle_increment = true;
954     params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
955     params->has_cpu_throttle_tailslow = true;
956     params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow;
957     params->tls_creds = g_strdup(s->parameters.tls_creds);
958     params->tls_hostname = g_strdup(s->parameters.tls_hostname);
959     params->tls_authz = g_strdup(s->parameters.tls_authz ?
960                                  s->parameters.tls_authz : "");
961     params->has_max_bandwidth = true;
962     params->max_bandwidth = s->parameters.max_bandwidth;
963     params->has_avail_switchover_bandwidth = true;
964     params->avail_switchover_bandwidth = s->parameters.avail_switchover_bandwidth;
965     params->has_downtime_limit = true;
966     params->downtime_limit = s->parameters.downtime_limit;
967     params->has_x_checkpoint_delay = true;
968     params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
969     params->has_multifd_channels = true;
970     params->multifd_channels = s->parameters.multifd_channels;
971     params->has_multifd_compression = true;
972     params->multifd_compression = s->parameters.multifd_compression;
973     params->has_multifd_zlib_level = true;
974     params->multifd_zlib_level = s->parameters.multifd_zlib_level;
975     params->has_multifd_zstd_level = true;
976     params->multifd_zstd_level = s->parameters.multifd_zstd_level;
977     params->has_xbzrle_cache_size = true;
978     params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
979     params->has_max_postcopy_bandwidth = true;
980     params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
981     params->has_max_cpu_throttle = true;
982     params->max_cpu_throttle = s->parameters.max_cpu_throttle;
983     params->has_announce_initial = true;
984     params->announce_initial = s->parameters.announce_initial;
985     params->has_announce_max = true;
986     params->announce_max = s->parameters.announce_max;
987     params->has_announce_rounds = true;
988     params->announce_rounds = s->parameters.announce_rounds;
989     params->has_announce_step = true;
990     params->announce_step = s->parameters.announce_step;
991 
992     if (s->parameters.has_block_bitmap_mapping) {
993         params->has_block_bitmap_mapping = true;
994         params->block_bitmap_mapping =
995             QAPI_CLONE(BitmapMigrationNodeAliasList,
996                        s->parameters.block_bitmap_mapping);
997     }
998 
999     params->has_x_vcpu_dirty_limit_period = true;
1000     params->x_vcpu_dirty_limit_period = s->parameters.x_vcpu_dirty_limit_period;
1001     params->has_vcpu_dirty_limit = true;
1002     params->vcpu_dirty_limit = s->parameters.vcpu_dirty_limit;
1003     params->has_mode = true;
1004     params->mode = s->parameters.mode;
1005     params->has_zero_page_detection = true;
1006     params->zero_page_detection = s->parameters.zero_page_detection;
1007 
1008     return params;
1009 }
1010 
1011 void migrate_params_init(MigrationParameters *params)
1012 {
1013     params->tls_hostname = g_strdup("");
1014     params->tls_creds = g_strdup("");
1015 
1016     /* Set has_* up only for parameter checks */
1017     params->has_compress_level = true;
1018     params->has_compress_threads = true;
1019     params->has_compress_wait_thread = true;
1020     params->has_decompress_threads = true;
1021     params->has_throttle_trigger_threshold = true;
1022     params->has_cpu_throttle_initial = true;
1023     params->has_cpu_throttle_increment = true;
1024     params->has_cpu_throttle_tailslow = true;
1025     params->has_max_bandwidth = true;
1026     params->has_downtime_limit = true;
1027     params->has_x_checkpoint_delay = true;
1028     params->has_multifd_channels = true;
1029     params->has_multifd_compression = true;
1030     params->has_multifd_zlib_level = true;
1031     params->has_multifd_zstd_level = true;
1032     params->has_xbzrle_cache_size = true;
1033     params->has_max_postcopy_bandwidth = true;
1034     params->has_max_cpu_throttle = true;
1035     params->has_announce_initial = true;
1036     params->has_announce_max = true;
1037     params->has_announce_rounds = true;
1038     params->has_announce_step = true;
1039     params->has_x_vcpu_dirty_limit_period = true;
1040     params->has_vcpu_dirty_limit = true;
1041     params->has_mode = true;
1042     params->has_zero_page_detection = true;
1043 }
1044 
1045 /*
1046  * Check whether the parameters are valid. Error will be put into errp
1047  * (if provided). Return true if valid, otherwise false.
1048  */
1049 bool migrate_params_check(MigrationParameters *params, Error **errp)
1050 {
1051     ERRP_GUARD();
1052 
1053     if (params->has_compress_level &&
1054         (params->compress_level > 9)) {
1055         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
1056                    "a value between 0 and 9");
1057         return false;
1058     }
1059 
1060     if (params->has_compress_threads && (params->compress_threads < 1)) {
1061         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1062                    "compress_threads",
1063                    "a value between 1 and 255");
1064         return false;
1065     }
1066 
1067     if (params->has_decompress_threads && (params->decompress_threads < 1)) {
1068         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1069                    "decompress_threads",
1070                    "a value between 1 and 255");
1071         return false;
1072     }
1073 
1074     if (params->has_throttle_trigger_threshold &&
1075         (params->throttle_trigger_threshold < 1 ||
1076          params->throttle_trigger_threshold > 100)) {
1077         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1078                    "throttle_trigger_threshold",
1079                    "an integer in the range of 1 to 100");
1080         return false;
1081     }
1082 
1083     if (params->has_cpu_throttle_initial &&
1084         (params->cpu_throttle_initial < 1 ||
1085          params->cpu_throttle_initial > 99)) {
1086         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1087                    "cpu_throttle_initial",
1088                    "an integer in the range of 1 to 99");
1089         return false;
1090     }
1091 
1092     if (params->has_cpu_throttle_increment &&
1093         (params->cpu_throttle_increment < 1 ||
1094          params->cpu_throttle_increment > 99)) {
1095         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1096                    "cpu_throttle_increment",
1097                    "an integer in the range of 1 to 99");
1098         return false;
1099     }
1100 
1101     if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) {
1102         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1103                    "max_bandwidth",
1104                    "an integer in the range of 0 to "stringify(SIZE_MAX)
1105                    " bytes/second");
1106         return false;
1107     }
1108 
1109     if (params->has_avail_switchover_bandwidth &&
1110         (params->avail_switchover_bandwidth > SIZE_MAX)) {
1111         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1112                    "avail_switchover_bandwidth",
1113                    "an integer in the range of 0 to "stringify(SIZE_MAX)
1114                    " bytes/second");
1115         return false;
1116     }
1117 
1118     if (params->has_downtime_limit &&
1119         (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) {
1120         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1121                    "downtime_limit",
1122                    "an integer in the range of 0 to "
1123                     stringify(MAX_MIGRATE_DOWNTIME)" ms");
1124         return false;
1125     }
1126 
1127     /* x_checkpoint_delay is now always positive */
1128 
1129     if (params->has_multifd_channels && (params->multifd_channels < 1)) {
1130         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1131                    "multifd_channels",
1132                    "a value between 1 and 255");
1133         return false;
1134     }
1135 
1136     if (params->has_multifd_zlib_level &&
1137         (params->multifd_zlib_level > 9)) {
1138         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zlib_level",
1139                    "a value between 0 and 9");
1140         return false;
1141     }
1142 
1143     if (params->has_multifd_zstd_level &&
1144         (params->multifd_zstd_level > 20)) {
1145         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_zstd_level",
1146                    "a value between 0 and 20");
1147         return false;
1148     }
1149 
1150     if (params->has_xbzrle_cache_size &&
1151         (params->xbzrle_cache_size < qemu_target_page_size() ||
1152          !is_power_of_2(params->xbzrle_cache_size))) {
1153         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1154                    "xbzrle_cache_size",
1155                    "a power of two no less than the target page size");
1156         return false;
1157     }
1158 
1159     if (params->has_max_cpu_throttle &&
1160         (params->max_cpu_throttle < params->cpu_throttle_initial ||
1161          params->max_cpu_throttle > 99)) {
1162         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1163                    "max_cpu_throttle",
1164                    "an integer in the range of cpu_throttle_initial to 99");
1165         return false;
1166     }
1167 
1168     if (params->has_announce_initial &&
1169         params->announce_initial > 100000) {
1170         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1171                    "announce_initial",
1172                    "a value between 0 and 100000");
1173         return false;
1174     }
1175     if (params->has_announce_max &&
1176         params->announce_max > 100000) {
1177         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1178                    "announce_max",
1179                    "a value between 0 and 100000");
1180        return false;
1181     }
1182     if (params->has_announce_rounds &&
1183         params->announce_rounds > 1000) {
1184         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1185                    "announce_rounds",
1186                    "a value between 0 and 1000");
1187        return false;
1188     }
1189     if (params->has_announce_step &&
1190         (params->announce_step < 1 ||
1191         params->announce_step > 10000)) {
1192         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1193                    "announce_step",
1194                    "a value between 0 and 10000");
1195        return false;
1196     }
1197 
1198     if (params->has_block_bitmap_mapping &&
1199         !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) {
1200         error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: ");
1201         return false;
1202     }
1203 
1204 #ifdef CONFIG_LINUX
1205     if (migrate_zero_copy_send() &&
1206         ((params->has_multifd_compression && params->multifd_compression) ||
1207          (params->tls_creds && *params->tls_creds))) {
1208         error_setg(errp,
1209                    "Zero copy only available for non-compressed non-TLS multifd migration");
1210         return false;
1211     }
1212 #endif
1213 
1214     if (migrate_mapped_ram() &&
1215         (migrate_multifd_compression() || migrate_tls())) {
1216         error_setg(errp,
1217                    "Mapped-ram only available for non-compressed non-TLS multifd migration");
1218         return false;
1219     }
1220 
1221     if (params->has_x_vcpu_dirty_limit_period &&
1222         (params->x_vcpu_dirty_limit_period < 1 ||
1223          params->x_vcpu_dirty_limit_period > 1000)) {
1224         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
1225                    "x-vcpu-dirty-limit-period",
1226                    "a value between 1 and 1000");
1227         return false;
1228     }
1229 
1230     if (params->has_vcpu_dirty_limit &&
1231         (params->vcpu_dirty_limit < 1)) {
1232         error_setg(errp,
1233                    "Parameter 'vcpu_dirty_limit' must be greater than 1 MB/s");
1234         return false;
1235     }
1236 
1237     return true;
1238 }
1239 
1240 static void migrate_params_test_apply(MigrateSetParameters *params,
1241                                       MigrationParameters *dest)
1242 {
1243     *dest = migrate_get_current()->parameters;
1244 
1245     /* TODO use QAPI_CLONE() instead of duplicating it inline */
1246 
1247     if (params->has_compress_level) {
1248         dest->compress_level = params->compress_level;
1249     }
1250 
1251     if (params->has_compress_threads) {
1252         dest->compress_threads = params->compress_threads;
1253     }
1254 
1255     if (params->has_compress_wait_thread) {
1256         dest->compress_wait_thread = params->compress_wait_thread;
1257     }
1258 
1259     if (params->has_decompress_threads) {
1260         dest->decompress_threads = params->decompress_threads;
1261     }
1262 
1263     if (params->has_throttle_trigger_threshold) {
1264         dest->throttle_trigger_threshold = params->throttle_trigger_threshold;
1265     }
1266 
1267     if (params->has_cpu_throttle_initial) {
1268         dest->cpu_throttle_initial = params->cpu_throttle_initial;
1269     }
1270 
1271     if (params->has_cpu_throttle_increment) {
1272         dest->cpu_throttle_increment = params->cpu_throttle_increment;
1273     }
1274 
1275     if (params->has_cpu_throttle_tailslow) {
1276         dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow;
1277     }
1278 
1279     if (params->tls_creds) {
1280         assert(params->tls_creds->type == QTYPE_QSTRING);
1281         dest->tls_creds = params->tls_creds->u.s;
1282     }
1283 
1284     if (params->tls_hostname) {
1285         assert(params->tls_hostname->type == QTYPE_QSTRING);
1286         dest->tls_hostname = params->tls_hostname->u.s;
1287     }
1288 
1289     if (params->has_max_bandwidth) {
1290         dest->max_bandwidth = params->max_bandwidth;
1291     }
1292 
1293     if (params->has_avail_switchover_bandwidth) {
1294         dest->avail_switchover_bandwidth = params->avail_switchover_bandwidth;
1295     }
1296 
1297     if (params->has_downtime_limit) {
1298         dest->downtime_limit = params->downtime_limit;
1299     }
1300 
1301     if (params->has_x_checkpoint_delay) {
1302         dest->x_checkpoint_delay = params->x_checkpoint_delay;
1303     }
1304 
1305     if (params->has_multifd_channels) {
1306         dest->multifd_channels = params->multifd_channels;
1307     }
1308     if (params->has_multifd_compression) {
1309         dest->multifd_compression = params->multifd_compression;
1310     }
1311     if (params->has_multifd_zlib_level) {
1312         dest->multifd_zlib_level = params->multifd_zlib_level;
1313     }
1314     if (params->has_multifd_zstd_level) {
1315         dest->multifd_zstd_level = params->multifd_zstd_level;
1316     }
1317     if (params->has_xbzrle_cache_size) {
1318         dest->xbzrle_cache_size = params->xbzrle_cache_size;
1319     }
1320     if (params->has_max_postcopy_bandwidth) {
1321         dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1322     }
1323     if (params->has_max_cpu_throttle) {
1324         dest->max_cpu_throttle = params->max_cpu_throttle;
1325     }
1326     if (params->has_announce_initial) {
1327         dest->announce_initial = params->announce_initial;
1328     }
1329     if (params->has_announce_max) {
1330         dest->announce_max = params->announce_max;
1331     }
1332     if (params->has_announce_rounds) {
1333         dest->announce_rounds = params->announce_rounds;
1334     }
1335     if (params->has_announce_step) {
1336         dest->announce_step = params->announce_step;
1337     }
1338 
1339     if (params->has_block_bitmap_mapping) {
1340         dest->has_block_bitmap_mapping = true;
1341         dest->block_bitmap_mapping = params->block_bitmap_mapping;
1342     }
1343 
1344     if (params->has_x_vcpu_dirty_limit_period) {
1345         dest->x_vcpu_dirty_limit_period =
1346             params->x_vcpu_dirty_limit_period;
1347     }
1348     if (params->has_vcpu_dirty_limit) {
1349         dest->vcpu_dirty_limit = params->vcpu_dirty_limit;
1350     }
1351 
1352     if (params->has_mode) {
1353         dest->mode = params->mode;
1354     }
1355 
1356     if (params->has_zero_page_detection) {
1357         dest->zero_page_detection = params->zero_page_detection;
1358     }
1359 }
1360 
1361 static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
1362 {
1363     MigrationState *s = migrate_get_current();
1364 
1365     /* TODO use QAPI_CLONE() instead of duplicating it inline */
1366 
1367     if (params->has_compress_level) {
1368         warn_report("old compression is deprecated;"
1369                     " use multifd compression methods instead");
1370         s->parameters.compress_level = params->compress_level;
1371     }
1372 
1373     if (params->has_compress_threads) {
1374         warn_report("old compression is deprecated;"
1375                     " use multifd compression methods instead");
1376         s->parameters.compress_threads = params->compress_threads;
1377     }
1378 
1379     if (params->has_compress_wait_thread) {
1380         warn_report("old compression is deprecated;"
1381                     " use multifd compression methods instead");
1382         s->parameters.compress_wait_thread = params->compress_wait_thread;
1383     }
1384 
1385     if (params->has_decompress_threads) {
1386         warn_report("old compression is deprecated;"
1387                     " use multifd compression methods instead");
1388         s->parameters.decompress_threads = params->decompress_threads;
1389     }
1390 
1391     if (params->has_throttle_trigger_threshold) {
1392         s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold;
1393     }
1394 
1395     if (params->has_cpu_throttle_initial) {
1396         s->parameters.cpu_throttle_initial = params->cpu_throttle_initial;
1397     }
1398 
1399     if (params->has_cpu_throttle_increment) {
1400         s->parameters.cpu_throttle_increment = params->cpu_throttle_increment;
1401     }
1402 
1403     if (params->has_cpu_throttle_tailslow) {
1404         s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow;
1405     }
1406 
1407     if (params->tls_creds) {
1408         g_free(s->parameters.tls_creds);
1409         assert(params->tls_creds->type == QTYPE_QSTRING);
1410         s->parameters.tls_creds = g_strdup(params->tls_creds->u.s);
1411     }
1412 
1413     if (params->tls_hostname) {
1414         g_free(s->parameters.tls_hostname);
1415         assert(params->tls_hostname->type == QTYPE_QSTRING);
1416         s->parameters.tls_hostname = g_strdup(params->tls_hostname->u.s);
1417     }
1418 
1419     if (params->tls_authz) {
1420         g_free(s->parameters.tls_authz);
1421         assert(params->tls_authz->type == QTYPE_QSTRING);
1422         s->parameters.tls_authz = g_strdup(params->tls_authz->u.s);
1423     }
1424 
1425     if (params->has_max_bandwidth) {
1426         s->parameters.max_bandwidth = params->max_bandwidth;
1427         if (s->to_dst_file && !migration_in_postcopy()) {
1428             migration_rate_set(s->parameters.max_bandwidth);
1429         }
1430     }
1431 
1432     if (params->has_avail_switchover_bandwidth) {
1433         s->parameters.avail_switchover_bandwidth = params->avail_switchover_bandwidth;
1434     }
1435 
1436     if (params->has_downtime_limit) {
1437         s->parameters.downtime_limit = params->downtime_limit;
1438     }
1439 
1440     if (params->has_x_checkpoint_delay) {
1441         s->parameters.x_checkpoint_delay = params->x_checkpoint_delay;
1442         colo_checkpoint_delay_set();
1443     }
1444 
1445     if (params->has_multifd_channels) {
1446         s->parameters.multifd_channels = params->multifd_channels;
1447     }
1448     if (params->has_multifd_compression) {
1449         s->parameters.multifd_compression = params->multifd_compression;
1450     }
1451     if (params->has_multifd_zlib_level) {
1452         s->parameters.multifd_zlib_level = params->multifd_zlib_level;
1453     }
1454     if (params->has_multifd_zstd_level) {
1455         s->parameters.multifd_zstd_level = params->multifd_zstd_level;
1456     }
1457     if (params->has_xbzrle_cache_size) {
1458         s->parameters.xbzrle_cache_size = params->xbzrle_cache_size;
1459         xbzrle_cache_resize(params->xbzrle_cache_size, errp);
1460     }
1461     if (params->has_max_postcopy_bandwidth) {
1462         s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1463         if (s->to_dst_file && migration_in_postcopy()) {
1464             migration_rate_set(s->parameters.max_postcopy_bandwidth);
1465         }
1466     }
1467     if (params->has_max_cpu_throttle) {
1468         s->parameters.max_cpu_throttle = params->max_cpu_throttle;
1469     }
1470     if (params->has_announce_initial) {
1471         s->parameters.announce_initial = params->announce_initial;
1472     }
1473     if (params->has_announce_max) {
1474         s->parameters.announce_max = params->announce_max;
1475     }
1476     if (params->has_announce_rounds) {
1477         s->parameters.announce_rounds = params->announce_rounds;
1478     }
1479     if (params->has_announce_step) {
1480         s->parameters.announce_step = params->announce_step;
1481     }
1482 
1483     if (params->has_block_bitmap_mapping) {
1484         qapi_free_BitmapMigrationNodeAliasList(
1485             s->parameters.block_bitmap_mapping);
1486 
1487         s->parameters.has_block_bitmap_mapping = true;
1488         s->parameters.block_bitmap_mapping =
1489             QAPI_CLONE(BitmapMigrationNodeAliasList,
1490                        params->block_bitmap_mapping);
1491     }
1492 
1493     if (params->has_x_vcpu_dirty_limit_period) {
1494         s->parameters.x_vcpu_dirty_limit_period =
1495             params->x_vcpu_dirty_limit_period;
1496     }
1497     if (params->has_vcpu_dirty_limit) {
1498         s->parameters.vcpu_dirty_limit = params->vcpu_dirty_limit;
1499     }
1500 
1501     if (params->has_mode) {
1502         s->parameters.mode = params->mode;
1503     }
1504 
1505     if (params->has_zero_page_detection) {
1506         s->parameters.zero_page_detection = params->zero_page_detection;
1507     }
1508 }
1509 
1510 void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
1511 {
1512     MigrationParameters tmp;
1513 
1514     /* TODO Rewrite "" to null instead for all three tls_* parameters */
1515     if (params->tls_creds
1516         && params->tls_creds->type == QTYPE_QNULL) {
1517         qobject_unref(params->tls_creds->u.n);
1518         params->tls_creds->type = QTYPE_QSTRING;
1519         params->tls_creds->u.s = strdup("");
1520     }
1521     if (params->tls_hostname
1522         && params->tls_hostname->type == QTYPE_QNULL) {
1523         qobject_unref(params->tls_hostname->u.n);
1524         params->tls_hostname->type = QTYPE_QSTRING;
1525         params->tls_hostname->u.s = strdup("");
1526     }
1527     if (params->tls_authz
1528         && params->tls_authz->type == QTYPE_QNULL) {
1529         qobject_unref(params->tls_authz->u.n);
1530         params->tls_authz->type = QTYPE_QSTRING;
1531         params->tls_authz->u.s = strdup("");
1532     }
1533 
1534     migrate_params_test_apply(params, &tmp);
1535 
1536     if (!migrate_params_check(&tmp, errp)) {
1537         /* Invalid parameter */
1538         return;
1539     }
1540 
1541     migrate_params_apply(params, errp);
1542 }
1543