xref: /cloud-hypervisor/vm-migration/src/protocol.rs (revision 88a9f799449c04180c6b9a21d3b9c0c4b57e2bd6)
1aa98589bSRob Bradford // Copyright © 2020 Intel Corporation
2aa98589bSRob Bradford //
3aa98589bSRob Bradford // SPDX-License-Identifier: Apache-2.0
4aa98589bSRob Bradford //
5aa98589bSRob Bradford 
62569621cSSebastien Boeuf use std::io::{Read, Write};
7*88a9f799SRob Bradford 
8*88a9f799SRob Bradford use serde::{Deserialize, Serialize};
98e9a5a0dSRob Bradford use vm_memory::ByteValued;
10aa98589bSRob Bradford 
11*88a9f799SRob Bradford use crate::MigratableError;
12*88a9f799SRob Bradford 
13aa98589bSRob Bradford // Migration protocol
14aa98589bSRob Bradford // 1: Source establishes communication with destination (file socket or TCP connection.)
15aa98589bSRob Bradford // (The establishment is out of scope.)
16aa98589bSRob Bradford // 2: Source -> Dest : send "start command"
17aa98589bSRob Bradford // 3: Dest -> Source : sends "ok response" when read to accept state data
1811a69450SRob Bradford // 4: Source -> Dest : sends "config command" followed by config data, length
1911a69450SRob Bradford //                     in command is length of config data
20aa98589bSRob Bradford // 5: Dest -> Source : sends "ok response" when ready to accept memory data
21aa98589bSRob Bradford // 6: Source -> Dest : send "memory command" followed by table of u64 pairs (GPA, size)
22aa98589bSRob Bradford //                     followed by the memory described in those pairs.
23aa98589bSRob Bradford //                     !! length is size of table i.e. 16 * number of ranges !!
24aa98589bSRob Bradford // 7: Dest -> Source : sends "ok response" when ready to accept more memory data
2511a69450SRob Bradford // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send
2611a69450SRob Bradford // (n-3): Source -> Dest : sends "state command" followed by state data, length
2711a69450SRob Bradford //                     in command is length of config data
2811a69450SRob Bradford // (n-2): Dest -> Source : sends "ok response"
29aa98589bSRob Bradford // (n-1): Source -> Dest : send "complete command"
30aa98589bSRob Bradford // n: Dest -> Source: sends "ok response"
3133fd0af8SRob Bradford //
3233fd0af8SRob Bradford // "Local version": (Handing FDs across socket for memory)
3333fd0af8SRob Bradford // 1: Source establishes communication with destination (file socket or TCP connection.)
3433fd0af8SRob Bradford // (The establishment is out of scope.)
3533fd0af8SRob Bradford // 2: Source -> Dest : send "start command"
3633fd0af8SRob Bradford // 3: Dest -> Source : sends "ok response" when read to accept state data
3733fd0af8SRob Bradford // 4: Source -> Dest : sends "config command" followed by config data, length
3833fd0af8SRob Bradford //                     in command is length of config data
3933fd0af8SRob Bradford // 5: Dest -> Source : sends "ok response" when ready to accept memory data
4033fd0af8SRob Bradford // 6: Source -> Dest : send "memory fd command" followed by u16 slot ID and FD for memory
4133fd0af8SRob Bradford // 7: Dest -> Source : sends "ok response" when received
4233fd0af8SRob Bradford // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send
4333fd0af8SRob Bradford // (n-3): Source -> Dest : sends "state command" followed by state data, length
4433fd0af8SRob Bradford //                     in command is length of config data
4533fd0af8SRob Bradford // (n-2): Dest -> Source : sends "ok response"
4633fd0af8SRob Bradford // (n-1): Source -> Dest : send "complete command"
4733fd0af8SRob Bradford // n: Dest -> Source: sends "ok response"
4833fd0af8SRob Bradford //
49aa98589bSRob Bradford // The destination can at any time send an "error response" to cancel
50aa98589bSRob Bradford // The source can at any time send an "abandon request" to cancel
51aa98589bSRob Bradford 
52aa98589bSRob Bradford #[repr(u16)]
53aa98589bSRob Bradford #[derive(Copy, Clone)]
54aa98589bSRob Bradford pub enum Command {
55aa98589bSRob Bradford     Invalid,
56aa98589bSRob Bradford     Start,
5711a69450SRob Bradford     Config,
58aa98589bSRob Bradford     State,
59aa98589bSRob Bradford     Memory,
60aa98589bSRob Bradford     Complete,
61aa98589bSRob Bradford     Abandon,
62735658a4SRob Bradford     MemoryFd,
63aa98589bSRob Bradford }
64aa98589bSRob Bradford 
65aa98589bSRob Bradford impl Default for Command {
default() -> Self66aa98589bSRob Bradford     fn default() -> Self {
67aa98589bSRob Bradford         Self::Invalid
68aa98589bSRob Bradford     }
69aa98589bSRob Bradford }
70aa98589bSRob Bradford 
71aa98589bSRob Bradford #[repr(C)]
728e9a5a0dSRob Bradford #[derive(Default, Copy, Clone)]
73aa98589bSRob Bradford pub struct Request {
74aa98589bSRob Bradford     command: Command,
75aa98589bSRob Bradford     padding: [u8; 6],
76aa98589bSRob Bradford     length: u64, // Length of payload for command excluding the Request struct
77aa98589bSRob Bradford }
78aa98589bSRob Bradford 
791a2b0188SWei Liu // SAFETY: Request contains a series of integers with no implicit padding
801a2b0188SWei Liu unsafe impl ByteValued for Request {}
811a2b0188SWei Liu 
82aa98589bSRob Bradford impl Request {
new(command: Command, length: u64) -> Self83aa98589bSRob Bradford     pub fn new(command: Command, length: u64) -> Self {
84aa98589bSRob Bradford         Self {
85aa98589bSRob Bradford             command,
86aa98589bSRob Bradford             length,
87aa98589bSRob Bradford             ..Default::default()
88aa98589bSRob Bradford         }
89aa98589bSRob Bradford     }
90aa98589bSRob Bradford 
start() -> Self91aa98589bSRob Bradford     pub fn start() -> Self {
92aa98589bSRob Bradford         Self::new(Command::Start, 0)
93aa98589bSRob Bradford     }
94aa98589bSRob Bradford 
state(length: u64) -> Self95aa98589bSRob Bradford     pub fn state(length: u64) -> Self {
96aa98589bSRob Bradford         Self::new(Command::State, length)
97aa98589bSRob Bradford     }
98aa98589bSRob Bradford 
config(length: u64) -> Self9911a69450SRob Bradford     pub fn config(length: u64) -> Self {
10011a69450SRob Bradford         Self::new(Command::Config, length)
10111a69450SRob Bradford     }
10211a69450SRob Bradford 
memory(length: u64) -> Self103aa98589bSRob Bradford     pub fn memory(length: u64) -> Self {
104aa98589bSRob Bradford         Self::new(Command::Memory, length)
105aa98589bSRob Bradford     }
106aa98589bSRob Bradford 
memory_fd(length: u64) -> Self107735658a4SRob Bradford     pub fn memory_fd(length: u64) -> Self {
108735658a4SRob Bradford         Self::new(Command::MemoryFd, length)
109735658a4SRob Bradford     }
110735658a4SRob Bradford 
complete() -> Self111aa98589bSRob Bradford     pub fn complete() -> Self {
112aa98589bSRob Bradford         Self::new(Command::Complete, 0)
113aa98589bSRob Bradford     }
114aa98589bSRob Bradford 
abandon() -> Self115aa98589bSRob Bradford     pub fn abandon() -> Self {
116aa98589bSRob Bradford         Self::new(Command::Abandon, 0)
117aa98589bSRob Bradford     }
118aa98589bSRob Bradford 
command(&self) -> Command119aa98589bSRob Bradford     pub fn command(&self) -> Command {
120aa98589bSRob Bradford         self.command
121aa98589bSRob Bradford     }
122aa98589bSRob Bradford 
length(&self) -> u64123aa98589bSRob Bradford     pub fn length(&self) -> u64 {
124aa98589bSRob Bradford         self.length
125aa98589bSRob Bradford     }
126aa98589bSRob Bradford 
read_from(fd: &mut dyn Read) -> Result<Request, MigratableError>127aa98589bSRob Bradford     pub fn read_from(fd: &mut dyn Read) -> Result<Request, MigratableError> {
128aa98589bSRob Bradford         let mut request = Request::default();
1298e9a5a0dSRob Bradford         fd.read_exact(Self::as_mut_slice(&mut request))
130aa98589bSRob Bradford             .map_err(MigratableError::MigrateSocket)?;
131aa98589bSRob Bradford 
132aa98589bSRob Bradford         Ok(request)
133aa98589bSRob Bradford     }
134aa98589bSRob Bradford 
write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>135aa98589bSRob Bradford     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
1368e9a5a0dSRob Bradford         fd.write_all(Self::as_slice(self))
137aa98589bSRob Bradford             .map_err(MigratableError::MigrateSocket)
138aa98589bSRob Bradford     }
139aa98589bSRob Bradford }
140aa98589bSRob Bradford 
141aa98589bSRob Bradford #[repr(u16)]
1422716bc33SRob Bradford #[derive(Copy, Clone, PartialEq, Eq)]
143aa98589bSRob Bradford pub enum Status {
144aa98589bSRob Bradford     Invalid,
145aa98589bSRob Bradford     Ok,
146aa98589bSRob Bradford     Error,
147aa98589bSRob Bradford }
148aa98589bSRob Bradford 
149aa98589bSRob Bradford impl Default for Status {
default() -> Self150aa98589bSRob Bradford     fn default() -> Self {
151aa98589bSRob Bradford         Self::Invalid
152aa98589bSRob Bradford     }
153aa98589bSRob Bradford }
154aa98589bSRob Bradford 
155aa98589bSRob Bradford #[repr(C)]
1568e9a5a0dSRob Bradford #[derive(Default, Copy, Clone)]
157aa98589bSRob Bradford pub struct Response {
158aa98589bSRob Bradford     status: Status,
159aa98589bSRob Bradford     padding: [u8; 6],
160aa98589bSRob Bradford     length: u64, // Length of payload for command excluding the Response struct
161aa98589bSRob Bradford }
162aa98589bSRob Bradford 
1631a2b0188SWei Liu // SAFETY: Response contains a series of integers with no implicit padding
1641a2b0188SWei Liu unsafe impl ByteValued for Response {}
1651a2b0188SWei Liu 
166aa98589bSRob Bradford impl Response {
new(status: Status, length: u64) -> Self167aa98589bSRob Bradford     pub fn new(status: Status, length: u64) -> Self {
168aa98589bSRob Bradford         Self {
169aa98589bSRob Bradford             status,
170aa98589bSRob Bradford             length,
171aa98589bSRob Bradford             ..Default::default()
172aa98589bSRob Bradford         }
173aa98589bSRob Bradford     }
174aa98589bSRob Bradford 
ok() -> Self175aa98589bSRob Bradford     pub fn ok() -> Self {
176aa98589bSRob Bradford         Self::new(Status::Ok, 0)
177aa98589bSRob Bradford     }
178aa98589bSRob Bradford 
error() -> Self179aa98589bSRob Bradford     pub fn error() -> Self {
180aa98589bSRob Bradford         Self::new(Status::Error, 0)
181aa98589bSRob Bradford     }
182aa98589bSRob Bradford 
status(&self) -> Status183aa98589bSRob Bradford     pub fn status(&self) -> Status {
184aa98589bSRob Bradford         self.status
185aa98589bSRob Bradford     }
186aa98589bSRob Bradford 
read_from(fd: &mut dyn Read) -> Result<Response, MigratableError>187aa98589bSRob Bradford     pub fn read_from(fd: &mut dyn Read) -> Result<Response, MigratableError> {
188aa98589bSRob Bradford         let mut response = Response::default();
1898e9a5a0dSRob Bradford         fd.read_exact(Self::as_mut_slice(&mut response))
190aa98589bSRob Bradford             .map_err(MigratableError::MigrateSocket)?;
191aa98589bSRob Bradford 
192aa98589bSRob Bradford         Ok(response)
193aa98589bSRob Bradford     }
194aa98589bSRob Bradford 
ok_or_abandon<T>( self, fd: &mut T, error: MigratableError, ) -> Result<Response, MigratableError> where T: Read + Write,195e97cee99SRob Bradford     pub fn ok_or_abandon<T>(
196e97cee99SRob Bradford         self,
197e97cee99SRob Bradford         fd: &mut T,
198e97cee99SRob Bradford         error: MigratableError,
199e97cee99SRob Bradford     ) -> Result<Response, MigratableError>
200e97cee99SRob Bradford     where
201e97cee99SRob Bradford         T: Read + Write,
202e97cee99SRob Bradford     {
203e97cee99SRob Bradford         if self.status != Status::Ok {
204e97cee99SRob Bradford             Request::abandon().write_to(fd)?;
205e97cee99SRob Bradford             Response::read_from(fd)?;
206e97cee99SRob Bradford             return Err(error);
207e97cee99SRob Bradford         }
208e97cee99SRob Bradford         Ok(self)
209e97cee99SRob Bradford     }
210e97cee99SRob Bradford 
write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>211aa98589bSRob Bradford     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
2128e9a5a0dSRob Bradford         fd.write_all(Self::as_slice(self))
213aa98589bSRob Bradford             .map_err(MigratableError::MigrateSocket)
214aa98589bSRob Bradford     }
215aa98589bSRob Bradford }
216aa98589bSRob Bradford 
217aa98589bSRob Bradford #[repr(C)]
21810ab87d6SRob Bradford #[derive(Clone, Default, Serialize, Deserialize)]
219aa98589bSRob Bradford pub struct MemoryRange {
220aa98589bSRob Bradford     pub gpa: u64,
221aa98589bSRob Bradford     pub length: u64,
222aa98589bSRob Bradford }
223aa98589bSRob Bradford 
22410ab87d6SRob Bradford #[derive(Clone, Default, Serialize, Deserialize)]
225aa98589bSRob Bradford pub struct MemoryRangeTable {
226aa98589bSRob Bradford     data: Vec<MemoryRange>,
227aa98589bSRob Bradford }
228aa98589bSRob Bradford 
229aa98589bSRob Bradford impl MemoryRangeTable {
from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self230a1caa654SSebastien Boeuf     pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64, page_size: u64) -> Self {
23179425b6aSSebastien Boeuf         let mut table = MemoryRangeTable::default();
23279425b6aSSebastien Boeuf         let mut entry: Option<MemoryRange> = None;
23379425b6aSSebastien Boeuf         for (i, block) in bitmap.iter().enumerate() {
23479425b6aSSebastien Boeuf             for j in 0..64 {
23579425b6aSSebastien Boeuf                 let is_page_dirty = ((block >> j) & 1u64) != 0u64;
23679425b6aSSebastien Boeuf                 let page_offset = ((i * 64) + j) as u64 * page_size;
23779425b6aSSebastien Boeuf                 if is_page_dirty {
23879425b6aSSebastien Boeuf                     if let Some(entry) = &mut entry {
23979425b6aSSebastien Boeuf                         entry.length += page_size;
24079425b6aSSebastien Boeuf                     } else {
24179425b6aSSebastien Boeuf                         entry = Some(MemoryRange {
24279425b6aSSebastien Boeuf                             gpa: start_addr + page_offset,
24379425b6aSSebastien Boeuf                             length: page_size,
24479425b6aSSebastien Boeuf                         });
24579425b6aSSebastien Boeuf                     }
24679425b6aSSebastien Boeuf                 } else if let Some(entry) = entry.take() {
24779425b6aSSebastien Boeuf                     table.push(entry);
24879425b6aSSebastien Boeuf                 }
24979425b6aSSebastien Boeuf             }
25079425b6aSSebastien Boeuf         }
25179425b6aSSebastien Boeuf         if let Some(entry) = entry.take() {
25279425b6aSSebastien Boeuf             table.push(entry);
25379425b6aSSebastien Boeuf         }
25479425b6aSSebastien Boeuf 
25579425b6aSSebastien Boeuf         table
25679425b6aSSebastien Boeuf     }
25779425b6aSSebastien Boeuf 
regions(&self) -> &[MemoryRange]258aa98589bSRob Bradford     pub fn regions(&self) -> &[MemoryRange] {
259aa98589bSRob Bradford         &self.data
260aa98589bSRob Bradford     }
261aa98589bSRob Bradford 
push(&mut self, range: MemoryRange)262aa98589bSRob Bradford     pub fn push(&mut self, range: MemoryRange) {
263aa98589bSRob Bradford         self.data.push(range)
264aa98589bSRob Bradford     }
265aa98589bSRob Bradford 
read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError>266aa98589bSRob Bradford     pub fn read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError> {
267aa98589bSRob Bradford         assert!(length as usize % std::mem::size_of::<MemoryRange>() == 0);
268aa98589bSRob Bradford 
269c8e3c1eeSSebastien Boeuf         let mut data: Vec<MemoryRange> = Vec::new();
270c8e3c1eeSSebastien Boeuf         data.resize_with(
271c8e3c1eeSSebastien Boeuf             length as usize / (std::mem::size_of::<MemoryRange>()),
272c8e3c1eeSSebastien Boeuf             Default::default,
273c8e3c1eeSSebastien Boeuf         );
2747bf0cc1eSPhilipp Schuster         // SAFETY: the slice is constructed with the correct arguments
275aa98589bSRob Bradford         fd.read_exact(unsafe {
276aa98589bSRob Bradford             std::slice::from_raw_parts_mut(
277aa98589bSRob Bradford                 data.as_ptr() as *mut MemoryRange as *mut u8,
278aa98589bSRob Bradford                 length as usize,
279aa98589bSRob Bradford             )
280aa98589bSRob Bradford         })
281aa98589bSRob Bradford         .map_err(MigratableError::MigrateSocket)?;
282aa98589bSRob Bradford 
283aa98589bSRob Bradford         Ok(Self { data })
284aa98589bSRob Bradford     }
285aa98589bSRob Bradford 
length(&self) -> u64286aa98589bSRob Bradford     pub fn length(&self) -> u64 {
287aa98589bSRob Bradford         (std::mem::size_of::<MemoryRange>() * self.data.len()) as u64
288aa98589bSRob Bradford     }
289aa98589bSRob Bradford 
write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError>290aa98589bSRob Bradford     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
2917bf0cc1eSPhilipp Schuster         // SAFETY: the slice is constructed with the correct arguments
292aa98589bSRob Bradford         fd.write_all(unsafe {
293aac614e2SYu Li             std::slice::from_raw_parts(self.data.as_ptr() as *const u8, self.length() as usize)
294aa98589bSRob Bradford         })
295aa98589bSRob Bradford         .map_err(MigratableError::MigrateSocket)
296aa98589bSRob Bradford     }
29779425b6aSSebastien Boeuf 
is_empty(&self) -> bool29879425b6aSSebastien Boeuf     pub fn is_empty(&self) -> bool {
29979425b6aSSebastien Boeuf         self.data.is_empty()
30079425b6aSSebastien Boeuf     }
30179425b6aSSebastien Boeuf 
extend(&mut self, table: Self)30279425b6aSSebastien Boeuf     pub fn extend(&mut self, table: Self) {
30379425b6aSSebastien Boeuf         self.data.extend(table.data)
30479425b6aSSebastien Boeuf     }
30579425b6aSSebastien Boeuf 
new_from_tables(tables: Vec<Self>) -> Self30679425b6aSSebastien Boeuf     pub fn new_from_tables(tables: Vec<Self>) -> Self {
30779425b6aSSebastien Boeuf         let mut data = Vec::new();
30879425b6aSSebastien Boeuf         for table in tables {
30979425b6aSSebastien Boeuf             data.extend(table.data);
31079425b6aSSebastien Boeuf         }
31179425b6aSSebastien Boeuf         Self { data }
31279425b6aSSebastien Boeuf     }
313aa98589bSRob Bradford }
314