xref: /cloud-hypervisor/vm-migration/src/protocol.rs (revision f7f2f25a574b1b2dba22c094fc8226d404157d15)
1 // Copyright © 2020 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 
6 use crate::MigratableError;
7 use vm_memory::ByteValued;
8 
9 // Migration protocol
10 // 1: Source establishes communication with destination (file socket or TCP connection.)
11 // (The establishment is out of scope.)
12 // 2: Source -> Dest : send "start command"
13 // 3: Dest -> Source : sends "ok response" when read to accept state data
14 // 4: Source -> Dest : sends "config command" followed by config data, length
15 //                     in command is length of config data
16 // 5: Dest -> Source : sends "ok response" when ready to accept memory data
17 // 6: Source -> Dest : send "memory command" followed by table of u64 pairs (GPA, size)
18 //                     followed by the memory described in those pairs.
19 //                     !! length is size of table i.e. 16 * number of ranges !!
20 // 7: Dest -> Source : sends "ok response" when ready to accept more memory data
21 // 8..(n-4): Repeat steps 6 and 7 until source has no more memory to send
22 // (n-3): Source -> Dest : sends "state command" followed by state data, length
23 //                     in command is length of config data
24 // (n-2): Dest -> Source : sends "ok response"
25 // (n-1): Source -> Dest : send "complete command"
26 // n: Dest -> Source: sends "ok response"
27 
28 // The destination can at any time send an "error response" to cancel
29 // The source can at any time send an "abandon request" to cancel
30 
31 use std::io::{Read, Write};
32 
33 #[repr(u16)]
34 #[derive(Copy, Clone)]
35 pub enum Command {
36     Invalid,
37     Start,
38     Config,
39     State,
40     Memory,
41     Complete,
42     Abandon,
43 }
44 
45 impl Default for Command {
46     fn default() -> Self {
47         Self::Invalid
48     }
49 }
50 
51 #[repr(C)]
52 #[derive(Default, Copy, Clone)]
53 pub struct Request {
54     command: Command,
55     padding: [u8; 6],
56     length: u64, // Length of payload for command excluding the Request struct
57 }
58 
59 impl Request {
60     pub fn new(command: Command, length: u64) -> Self {
61         Self {
62             command,
63             length,
64             ..Default::default()
65         }
66     }
67 
68     pub fn start() -> Self {
69         Self::new(Command::Start, 0)
70     }
71 
72     pub fn state(length: u64) -> Self {
73         Self::new(Command::State, length)
74     }
75 
76     pub fn config(length: u64) -> Self {
77         Self::new(Command::Config, length)
78     }
79 
80     pub fn memory(length: u64) -> Self {
81         Self::new(Command::Memory, length)
82     }
83 
84     pub fn complete() -> Self {
85         Self::new(Command::Complete, 0)
86     }
87 
88     pub fn abandon() -> Self {
89         Self::new(Command::Abandon, 0)
90     }
91 
92     pub fn command(&self) -> Command {
93         self.command
94     }
95 
96     pub fn length(&self) -> u64 {
97         self.length
98     }
99 
100     pub fn read_from(fd: &mut dyn Read) -> Result<Request, MigratableError> {
101         let mut request = Request::default();
102         fd.read_exact(Self::as_mut_slice(&mut request))
103             .map_err(MigratableError::MigrateSocket)?;
104 
105         Ok(request)
106     }
107 
108     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
109         fd.write_all(Self::as_slice(self))
110             .map_err(MigratableError::MigrateSocket)
111     }
112 }
113 
114 unsafe impl ByteValued for Request {}
115 
116 #[repr(u16)]
117 #[derive(Copy, Clone, PartialEq)]
118 pub enum Status {
119     Invalid,
120     Ok,
121     Error,
122 }
123 
124 impl Default for Status {
125     fn default() -> Self {
126         Self::Invalid
127     }
128 }
129 
130 #[repr(C)]
131 #[derive(Default, Copy, Clone)]
132 pub struct Response {
133     status: Status,
134     padding: [u8; 6],
135     length: u64, // Length of payload for command excluding the Response struct
136 }
137 
138 impl Response {
139     pub fn new(status: Status, length: u64) -> Self {
140         Self {
141             status,
142             length,
143             ..Default::default()
144         }
145     }
146 
147     pub fn ok() -> Self {
148         Self::new(Status::Ok, 0)
149     }
150 
151     pub fn error() -> Self {
152         Self::new(Status::Error, 0)
153     }
154 
155     pub fn status(&self) -> Status {
156         self.status
157     }
158 
159     pub fn read_from(fd: &mut dyn Read) -> Result<Response, MigratableError> {
160         let mut response = Response::default();
161         fd.read_exact(Self::as_mut_slice(&mut response))
162             .map_err(MigratableError::MigrateSocket)?;
163 
164         Ok(response)
165     }
166 
167     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
168         fd.write_all(Self::as_slice(self))
169             .map_err(MigratableError::MigrateSocket)
170     }
171 }
172 
173 unsafe impl ByteValued for Response {}
174 
175 #[repr(C)]
176 pub struct MemoryRange {
177     pub gpa: u64,
178     pub length: u64,
179 }
180 
181 #[derive(Default)]
182 pub struct MemoryRangeTable {
183     data: Vec<MemoryRange>,
184 }
185 
186 impl MemoryRangeTable {
187     pub fn from_bitmap(bitmap: Vec<u64>, start_addr: u64) -> Self {
188         let page_size = 4096;
189         let mut table = MemoryRangeTable::default();
190         let mut entry: Option<MemoryRange> = None;
191         for (i, block) in bitmap.iter().enumerate() {
192             for j in 0..64 {
193                 let is_page_dirty = ((block >> j) & 1u64) != 0u64;
194                 let page_offset = ((i * 64) + j) as u64 * page_size;
195                 if is_page_dirty {
196                     if let Some(entry) = &mut entry {
197                         entry.length += page_size;
198                     } else {
199                         entry = Some(MemoryRange {
200                             gpa: start_addr + page_offset,
201                             length: page_size,
202                         });
203                     }
204                 } else if let Some(entry) = entry.take() {
205                     table.push(entry);
206                 }
207             }
208         }
209         if let Some(entry) = entry.take() {
210             table.push(entry);
211         }
212 
213         table
214     }
215 
216     pub fn regions(&self) -> &[MemoryRange] {
217         &self.data
218     }
219 
220     pub fn push(&mut self, range: MemoryRange) {
221         self.data.push(range)
222     }
223 
224     pub fn read_from(fd: &mut dyn Read, length: u64) -> Result<MemoryRangeTable, MigratableError> {
225         assert!(length as usize % std::mem::size_of::<MemoryRange>() == 0);
226 
227         let mut data = Vec::with_capacity(length as usize / (std::mem::size_of::<MemoryRange>()));
228         unsafe {
229             data.set_len(length as usize / (std::mem::size_of::<MemoryRange>()));
230         }
231         fd.read_exact(unsafe {
232             std::slice::from_raw_parts_mut(
233                 data.as_ptr() as *mut MemoryRange as *mut u8,
234                 length as usize,
235             )
236         })
237         .map_err(MigratableError::MigrateSocket)?;
238 
239         Ok(Self { data })
240     }
241 
242     pub fn length(&self) -> u64 {
243         (std::mem::size_of::<MemoryRange>() * self.data.len()) as u64
244     }
245 
246     pub fn write_to(&self, fd: &mut dyn Write) -> Result<(), MigratableError> {
247         fd.write_all(unsafe {
248             std::slice::from_raw_parts(
249                 self.data.as_ptr() as *const MemoryRange as *const u8,
250                 self.length() as usize,
251             )
252         })
253         .map_err(MigratableError::MigrateSocket)
254     }
255 
256     pub fn is_empty(&self) -> bool {
257         self.data.is_empty()
258     }
259 
260     pub fn extend(&mut self, table: Self) {
261         self.data.extend(table.data)
262     }
263 
264     pub fn new_from_tables(tables: Vec<Self>) -> Self {
265         let mut data = Vec::new();
266         for table in tables {
267             data.extend(table.data);
268         }
269         Self { data }
270     }
271 }
272