vmbus_relay/
legacy_saved_state.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Provides saved state structures for compatibility with the 2411 release,
5//! where the relay and `vmbus_client` were saved together as a single state
6//! unit.
7
8pub use relay::SavedState;
9
10use crate::saved_state;
11
12mod relay {
13    use mesh::payload::Protobuf;
14    use vmcore::save_restore::SavedStateRoot;
15
16    /// The legacy, 2411 saved state for the relay.
17    #[derive(Clone, Protobuf, SavedStateRoot)]
18    #[mesh(package = "vmbus.relay")]
19    pub struct SavedState {
20        #[mesh(1)]
21        pub(crate) use_interrupt_relay: bool,
22        #[mesh(2)]
23        pub(super) relay_state: RelayState,
24        #[mesh(3)]
25        pub(super) client_saved_state: vmbus_client::SavedState,
26        #[mesh(4)]
27        pub(crate) channels: Vec<Channel>,
28    }
29
30    #[derive(Clone, Protobuf)]
31    #[mesh(package = "vmbus.relay")]
32    pub(crate) struct Channel {
33        #[mesh(1)]
34        pub(crate) channel_id: u32,
35        #[mesh(2)]
36        pub(crate) event_flag: Option<u16>,
37        #[mesh(3)]
38        pub(crate) intercepted: bool,
39        #[mesh(4)]
40        pub(crate) intercepted_save_state: Vec<u8>,
41    }
42
43    #[derive(Copy, Clone, Eq, PartialEq, Protobuf)]
44    #[mesh(package = "vmbus.relay")]
45    pub(super) enum RelayState {
46        #[mesh(1)]
47        Disconnected,
48        #[mesh(2)]
49        Connected,
50    }
51}
52
53impl SavedState {
54    /// Constructs a legacy saved state from the current relay and client saved
55    /// states.
56    pub fn from_relay_and_client(
57        relay: &saved_state::SavedState,
58        client: &vmbus_client::SavedState,
59    ) -> Self {
60        Self {
61            use_interrupt_relay: relay.use_interrupt_relay,
62            relay_state: relay::RelayState::Connected,
63            client_saved_state: client.clone(),
64            channels: relay
65                .channels
66                .iter()
67                .map(|channel| relay::Channel {
68                    channel_id: channel.channel_id,
69                    event_flag: channel.event_flag,
70                    intercepted: channel.intercepted,
71                    intercepted_save_state: channel.intercepted_save_state.clone(),
72                })
73                .collect(),
74        }
75    }
76
77    /// Produces a current relay saved state from the legacy saved state.
78    pub fn relay_saved_state(&mut self) -> saved_state::SavedState {
79        self.client_saved_state
80            .channels
81            .sort_by_key(|channel| channel.offer.channel_id);
82
83        saved_state::SavedState {
84            use_interrupt_relay: self.use_interrupt_relay,
85            channels: self
86                .channels
87                .iter()
88                .map(|channel| saved_state::Channel {
89                    channel_id: channel.channel_id,
90                    event_flag: channel.event_flag,
91                    intercepted: channel.intercepted,
92                    intercepted_save_state: channel.intercepted_save_state.clone(),
93                    is_open: self
94                        .client_saved_state
95                        .channels
96                        .binary_search_by_key(&channel.channel_id, |channel| {
97                            channel.offer.channel_id
98                        })
99                        .is_ok_and(|i| {
100                            matches!(
101                                self.client_saved_state.channels[i].state,
102                                vmbus_client::saved_state::ChannelState::Opened
103                            )
104                        }),
105                })
106                .collect(),
107        }
108    }
109
110    /// Produces a current client saved state from the legacy saved state.
111    pub fn client_saved_state(&self) -> vmbus_client::SavedState {
112        self.client_saved_state.clone()
113    }
114}