@@ -21,7 +21,6 @@ use std::collections::HashMap;
2121use std:: fs:: File ;
2222use std:: io:: { ErrorKind , Read , Write , stdout} ;
2323use std:: net:: { TcpListener , TcpStream } ;
24- use std:: num:: NonZeroU32 ;
2524use std:: os:: fd:: { AsFd , BorrowedFd } ;
2625use std:: os:: unix:: io:: { AsRawFd , FromRawFd , RawFd } ;
2726use std:: os:: unix:: net:: { UnixListener , UnixStream } ;
@@ -60,7 +59,9 @@ use vm_memory::{
6059} ;
6160use vm_migration:: protocol:: * ;
6261use vm_migration:: tls:: { TlsConnectionWrapper , TlsStream } ;
63- use vm_migration:: { Migratable , MigratableError , Pausable , Snapshot , Snapshottable , Transportable } ;
62+ use vm_migration:: {
63+ Migratable , MigratableError , Pausable , Snapshot , Snapshottable , Transportable , tls,
64+ } ;
6465use vmm_sys_util:: eventfd:: EventFd ;
6566use vmm_sys_util:: signal:: unblock_signal;
6667use vmm_sys_util:: sock_ctrl_msg:: ScmSocket ;
@@ -1232,15 +1233,15 @@ impl SendAdditionalConnections {
12321233 const CHUNK_SIZE : u64 = 64 /* MiB */ << 20 ;
12331234
12341235 fn new (
1235- destination : & str ,
1236- connections : NonZeroU32 ,
1236+ send_data_migration : & VmSendMigrationData ,
12371237 guest_mem : & GuestMemoryAtomic < GuestMemoryMmap > ,
12381238 ) -> std:: result:: Result < Self , MigratableError > {
12391239 let mut threads = Vec :: new ( ) ;
12401240 let mut channels = Vec :: new ( ) ;
12411241
1242- for n in 0 ..( connections. get ( ) - 1 ) {
1243- let socket = ( match send_migration_socket ( destination) {
1242+ let additional_connections = send_data_migration. connections . get ( ) - 1 ;
1243+ for n in 0 ..( additional_connections) {
1244+ let socket = ( match send_migration_socket ( send_data_migration) {
12441245 Err ( e) if n == 0 => {
12451246 // If we encounter a problem on the first additional
12461247 // connection, we just assume the other side doesn't support
@@ -1384,17 +1385,31 @@ impl Drop for SendAdditionalConnections {
13841385
13851386/// Establishes a connection to a migration destination socket (TCP or UNIX).
13861387fn send_migration_socket (
1387- destination_url : & str ,
1388+ send_data_migration : & VmSendMigrationData ,
13881389) -> std:: result:: Result < SocketStream , MigratableError > {
1389- if let Some ( address) = destination_url. strip_prefix ( "tcp:" ) {
1390+ if let Some ( address) = send_data_migration . destination_url . strip_prefix ( "tcp:" ) {
13901391 info ! ( "Connecting to TCP socket at {}" , address) ;
13911392
13921393 let socket = TcpStream :: connect ( address) . map_err ( |e| {
13931394 MigratableError :: MigrateSend ( anyhow ! ( "Error connecting to TCP socket: {}" , e) )
13941395 } ) ?;
13951396
1396- Ok ( SocketStream :: Tcp ( socket) )
1397- } else if let Some ( path) = destination_url. strip_prefix ( "unix:" ) {
1397+ if send_data_migration. tls_dir . is_none ( ) {
1398+ Ok ( SocketStream :: Tcp ( socket) )
1399+ } else {
1400+ info ! ( "Live Migration will be encrypted using TLS." ) ;
1401+ // The address may still contain a port. I think we should build something more robust to also handle IPv6.
1402+ let tls_stream = tls:: client_stream (
1403+ socket,
1404+ send_data_migration. tls_dir . as_ref ( ) . unwrap ( ) ,
1405+ address
1406+ . split_once ( ':' )
1407+ . map ( |( host, _) | host)
1408+ . unwrap_or ( address) ,
1409+ ) ?;
1410+ Ok ( SocketStream :: Tls ( TlsStream :: Client ( tls_stream) ) )
1411+ }
1412+ } else if let Some ( path) = & send_data_migration. destination_url . strip_prefix ( "unix:" ) {
13981413 info ! ( "Connecting to UNIX socket at {:?}" , path) ;
13991414
14001415 let socket = UnixStream :: connect ( path) . map_err ( |e| {
@@ -1404,30 +1419,39 @@ fn send_migration_socket(
14041419 Ok ( SocketStream :: Unix ( socket) )
14051420 } else {
14061421 Err ( MigratableError :: MigrateSend ( anyhow ! (
1407- "Invalid destination: {destination_url}"
1422+ "Invalid destination: {}" ,
1423+ send_data_migration. destination_url
14081424 ) ) )
14091425 }
14101426}
14111427
14121428/// Creates a listener socket for receiving incoming migration connections (TCP or UNIX).
14131429fn receive_migration_listener (
1414- receiver_url : & str ,
1430+ receiver_data_migration : & VmReceiveMigrationData ,
14151431) -> std:: result:: Result < ReceiveListener , MigratableError > {
1416- if let Some ( address) = receiver_url. strip_prefix ( "tcp:" ) {
1417- TcpListener :: bind ( address)
1418- . map_err ( |e| {
1419- MigratableError :: MigrateReceive ( anyhow ! ( "Error binding to TCP socket: {}" , e) )
1420- } )
1421- . map ( ReceiveListener :: Tcp )
1422- } else if let Some ( path) = receiver_url. strip_prefix ( "unix:" ) {
1432+ if let Some ( address) = receiver_data_migration. receiver_url . strip_prefix ( "tcp:" ) {
1433+ let listener = TcpListener :: bind ( address) . map_err ( |e| {
1434+ MigratableError :: MigrateReceive ( anyhow ! ( "Error binding to TCP socket: {}" , e) )
1435+ } ) ?;
1436+
1437+ if receiver_data_migration. tls_dir . is_none ( ) {
1438+ Ok ( ReceiveListener :: Tcp ( listener) )
1439+ } else {
1440+ Ok ( ReceiveListener :: Tls (
1441+ listener,
1442+ TlsConnectionWrapper :: new ( receiver_data_migration. tls_dir . as_ref ( ) . unwrap ( ) ) ,
1443+ ) )
1444+ }
1445+ } else if let Some ( path) = receiver_data_migration. receiver_url . strip_prefix ( "unix:" ) {
14231446 UnixListener :: bind ( path)
14241447 . map_err ( |e| {
14251448 MigratableError :: MigrateReceive ( anyhow ! ( "Error binding to UNIX socket: {}" , e) )
14261449 } )
14271450 . map ( |listener| ReceiveListener :: Unix ( listener, Some ( path. into ( ) ) ) )
14281451 } else {
14291452 Err ( MigratableError :: MigrateSend ( anyhow ! (
1430- "Invalid source: {receiver_url}"
1453+ "Invalid source: {}" ,
1454+ receiver_data_migration. receiver_url
14311455 ) ) )
14321456 }
14331457}
@@ -2054,11 +2078,7 @@ impl Vmm {
20542078 s : & mut MigrationState ,
20552079 send_data_migration : & VmSendMigrationData ,
20562080 ) -> result:: Result < ( ) , MigratableError > {
2057- let mem_send = SendAdditionalConnections :: new (
2058- & send_data_migration. destination_url ,
2059- send_data_migration. connections ,
2060- & vm. guest_memory ( ) ,
2061- ) ?;
2081+ let mem_send = SendAdditionalConnections :: new ( send_data_migration, & vm. guest_memory ( ) ) ?;
20622082
20632083 // Start logging dirty pages
20642084 vm. start_dirty_log ( ) ?;
@@ -2139,7 +2159,7 @@ impl Vmm {
21392159 let mut s = MigrationState :: new ( ) ;
21402160
21412161 // Set up the socket connection
2142- let mut socket = send_migration_socket ( & send_data_migration. destination_url ) ?;
2162+ let mut socket = send_migration_socket ( & send_data_migration) ?;
21432163
21442164 // Start the migration
21452165 Request :: start ( ) . write_to ( & mut socket) ?;
@@ -3317,7 +3337,7 @@ impl RequestHandler for Vmm {
33173337 receive_data_migration. receiver_url, & receive_data_migration. net_fds
33183338 ) ;
33193339
3320- let mut listener = receive_migration_listener ( & receive_data_migration. receiver_url ) ?;
3340+ let mut listener = receive_migration_listener ( & receive_data_migration) ?;
33213341 // Accept the connection and get the socket
33223342 let mut socket = listener. accept ( ) . map_err ( |e| {
33233343 warn ! ( "Failed to accept migration connection: {}" , e) ;
0 commit comments