socket.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * QEMU live migration via socket
  3. *
  4. * Copyright Red Hat, Inc. 2009-2016
  5. *
  6. * Authors:
  7. * Chris Lalancette <clalance@redhat.com>
  8. * Daniel P. Berrange <berrange@redhat.com>
  9. *
  10. * This work is licensed under the terms of the GNU GPL, version 2. See
  11. * the COPYING file in the top-level directory.
  12. *
  13. * Contributions after 2012-01-13 are licensed under the terms of the
  14. * GNU GPL, version 2 or (at your option) any later version.
  15. */
  16. #include "qemu/osdep.h"
  17. #include "qemu/cutils.h"
  18. #include "qemu/error-report.h"
  19. #include "qapi/error.h"
  20. #include "channel.h"
  21. #include "socket.h"
  22. #include "migration.h"
  23. #include "qemu-file.h"
  24. #include "io/channel-socket.h"
  25. #include "io/net-listener.h"
  26. #include "trace.h"
  27. #include "postcopy-ram.h"
  28. #include "options.h"
  29. #include "qapi/clone-visitor.h"
  30. #include "qapi/qapi-visit-sockets.h"
  31. struct SocketOutgoingArgs {
  32. SocketAddress *saddr;
  33. } outgoing_args;
  34. void socket_send_channel_create(QIOTaskFunc f, void *data)
  35. {
  36. QIOChannelSocket *sioc = qio_channel_socket_new();
  37. qio_channel_socket_connect_async(sioc, outgoing_args.saddr,
  38. f, data, NULL, NULL);
  39. }
  40. struct SocketConnectData {
  41. MigrationState *s;
  42. char *hostname;
  43. };
  44. static void socket_connect_data_free(void *opaque)
  45. {
  46. struct SocketConnectData *data = opaque;
  47. if (!data) {
  48. return;
  49. }
  50. g_free(data->hostname);
  51. g_free(data);
  52. }
  53. static void socket_outgoing_migration(QIOTask *task,
  54. gpointer opaque)
  55. {
  56. struct SocketConnectData *data = opaque;
  57. QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
  58. Error *err = NULL;
  59. if (qio_task_propagate_error(task, &err)) {
  60. trace_migration_socket_outgoing_error(error_get_pretty(err));
  61. goto out;
  62. }
  63. trace_migration_socket_outgoing_connected(data->hostname);
  64. if (migrate_zero_copy_send() &&
  65. !qio_channel_has_feature(sioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
  66. error_setg(&err, "Zero copy send feature not detected in host kernel");
  67. }
  68. out:
  69. migration_channel_connect(data->s, sioc, data->hostname, err);
  70. object_unref(OBJECT(sioc));
  71. }
  72. void socket_start_outgoing_migration(MigrationState *s,
  73. SocketAddress *saddr,
  74. Error **errp)
  75. {
  76. QIOChannelSocket *sioc = qio_channel_socket_new();
  77. struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
  78. SocketAddress *addr = QAPI_CLONE(SocketAddress, saddr);
  79. data->s = s;
  80. /* in case previous migration leaked it */
  81. qapi_free_SocketAddress(outgoing_args.saddr);
  82. outgoing_args.saddr = addr;
  83. if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
  84. data->hostname = g_strdup(saddr->u.inet.host);
  85. }
  86. qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-outgoing");
  87. qio_channel_socket_connect_async(sioc,
  88. saddr,
  89. socket_outgoing_migration,
  90. data,
  91. socket_connect_data_free,
  92. NULL);
  93. }
  94. void socket_cleanup_outgoing_migration(void)
  95. {
  96. if (outgoing_args.saddr) {
  97. qapi_free_SocketAddress(outgoing_args.saddr);
  98. outgoing_args.saddr = NULL;
  99. }
  100. }
  101. static void socket_accept_incoming_migration(QIONetListener *listener,
  102. QIOChannelSocket *cioc,
  103. gpointer opaque)
  104. {
  105. trace_migration_socket_incoming_accepted();
  106. if (migration_has_all_channels()) {
  107. error_report("%s: Extra incoming migration connection; ignoring",
  108. __func__);
  109. return;
  110. }
  111. qio_channel_set_name(QIO_CHANNEL(cioc), "migration-socket-incoming");
  112. migration_channel_process_incoming(QIO_CHANNEL(cioc));
  113. }
  114. static void
  115. socket_incoming_migration_end(void *opaque)
  116. {
  117. QIONetListener *listener = opaque;
  118. qio_net_listener_disconnect(listener);
  119. object_unref(OBJECT(listener));
  120. }
  121. void socket_start_incoming_migration(SocketAddress *saddr,
  122. Error **errp)
  123. {
  124. QIONetListener *listener = qio_net_listener_new();
  125. MigrationIncomingState *mis = migration_incoming_get_current();
  126. size_t i;
  127. int num = 1;
  128. qio_net_listener_set_name(listener, "migration-socket-listener");
  129. if (migrate_multifd()) {
  130. num = migrate_multifd_channels();
  131. } else if (migrate_postcopy_preempt()) {
  132. num = RAM_CHANNEL_MAX;
  133. }
  134. if (qio_net_listener_open_sync(listener, saddr, num, errp) < 0) {
  135. object_unref(OBJECT(listener));
  136. return;
  137. }
  138. mis->transport_data = listener;
  139. mis->transport_cleanup = socket_incoming_migration_end;
  140. qio_net_listener_set_client_func_full(listener,
  141. socket_accept_incoming_migration,
  142. NULL, NULL,
  143. g_main_context_get_thread_default());
  144. for (i = 0; i < listener->nsioc; i++) {
  145. SocketAddress *address =
  146. qio_channel_socket_get_local_address(listener->sioc[i], errp);
  147. if (!address) {
  148. return;
  149. }
  150. migrate_add_address(address);
  151. qapi_free_SocketAddress(address);
  152. }
  153. }