1pub mod saved_state;
5#[cfg(test)]
6mod tests;
7
8use crate::Guid;
9use crate::SynicMessage;
10use crate::monitor::AssignedMonitors;
11use crate::protocol::Version;
12use hvdef::Vtl;
13use inspect::Inspect;
14pub use saved_state::RestoreError;
15pub use saved_state::SavedState;
16pub use saved_state::SavedStateData;
17use slab::Slab;
18use std::cmp::min;
19use std::collections::VecDeque;
20use std::collections::hash_map::Entry;
21use std::collections::hash_map::HashMap;
22use std::fmt::Display;
23use std::ops::Index;
24use std::ops::IndexMut;
25use std::task::Poll;
26use std::task::ready;
27use std::time::Duration;
28use thiserror::Error;
29use vmbus_channel::bus::ChannelType;
30use vmbus_channel::bus::GpadlRequest;
31use vmbus_channel::bus::OfferKey;
32use vmbus_channel::bus::OfferParams;
33use vmbus_channel::bus::OpenData;
34use vmbus_channel::bus::RestoredGpadl;
35use vmbus_core::HvsockConnectRequest;
36use vmbus_core::HvsockConnectResult;
37use vmbus_core::MaxVersionInfo;
38use vmbus_core::OutgoingMessage;
39use vmbus_core::VMBUS_SINT;
40use vmbus_core::VersionInfo;
41use vmbus_core::protocol;
42use vmbus_core::protocol::ChannelId;
43use vmbus_core::protocol::ConnectionId;
44use vmbus_core::protocol::FeatureFlags;
45use vmbus_core::protocol::GpadlId;
46use vmbus_core::protocol::Message;
47use vmbus_core::protocol::OfferFlags;
48use vmbus_core::protocol::UserDefinedData;
49use vmbus_ring::gparange;
50use vmcore::monitor::MonitorId;
51use vmcore::synic::MonitorInfo;
52use vmcore::synic::MonitorPageGpas;
53use zerocopy::FromZeros;
54use zerocopy::Immutable;
55use zerocopy::IntoBytes;
56use zerocopy::KnownLayout;
57
58#[derive(Debug, Error)]
60pub enum ChannelError {
61 #[error("unknown channel ID")]
62 UnknownChannelId,
63 #[error("unknown GPADL ID")]
64 UnknownGpadlId,
65 #[error("parse error")]
66 ParseError(#[from] protocol::ParseError),
67 #[error("invalid gpa range")]
68 InvalidGpaRange(#[source] gparange::Error),
69 #[error("duplicate GPADL ID")]
70 DuplicateGpadlId,
71 #[error("GPADL is already complete")]
72 GpadlAlreadyComplete,
73 #[error("GPADL channel ID mismatch")]
74 WrongGpadlChannelId,
75 #[error("trying to open an open channel")]
76 ChannelAlreadyOpen,
77 #[error("trying to close a closed channel")]
78 ChannelNotOpen,
79 #[error("invalid GPADL state for operation")]
80 InvalidGpadlState,
81 #[error("invalid channel state for operation")]
82 InvalidChannelState,
83 #[error("channel ID has already been released")]
84 ChannelReleased,
85 #[error("channel offers have already been sent")]
86 OffersAlreadySent,
87 #[error("invalid operation on reserved channel")]
88 ChannelReserved,
89 #[error("invalid operation on non-reserved channel")]
90 ChannelNotReserved,
91 #[error("received untrusted message for trusted connection")]
92 UntrustedMessage,
93 #[error("received a non-resuming message while paused")]
94 Paused,
95 #[error("invalid target VP")]
96 InvalidTargetVp,
97 #[error("interrupts are disabled for this channel")]
98 InterruptsDisabled,
99}
100
101#[derive(Debug, Error)]
102pub enum OfferError {
103 #[error("the channel ID {} is not valid for this operation", (.0).0)]
104 InvalidChannelId(ChannelId),
105 #[error("the channel ID {} is already in use", (.0).0)]
106 ChannelIdInUse(ChannelId),
107 #[error("offer {0} already exists")]
108 AlreadyExists(OfferKey),
109 #[error("specified resources do not match those of the existing saved or revoked offer")]
110 IncompatibleResources,
111 #[error("too many channels have been offered")]
112 TooManyChannels,
113 #[error("mismatched monitor ID from saved state; expected {0:?}, actual {1:?}")]
114 MismatchedMonitorId(Option<MonitorId>, MonitorId),
115}
116
117#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
119pub struct OfferId(usize);
120
121type IncompleteGpadlMap = HashMap<GpadlId, OfferId>;
122
123type GpadlMap = HashMap<(GpadlId, OfferId), Gpadl>;
124
125pub struct Server {
127 state: ConnectionState,
128 channels: ChannelList,
129 assigned_channels: AssignedChannels,
130 assigned_monitors: AssignedMonitors,
131 gpadls: GpadlMap,
132 incomplete_gpadls: IncompleteGpadlMap,
133 child_connection_id: u32,
134 max_version: Option<MaxVersionInfo>,
136 delayed_max_version: Option<MaxVersionInfo>,
140 max_restore_version: Option<MaxVersionInfo>,
143 pending_messages: PendingMessages,
146 require_server_allocated_mnf: bool,
150 use_absolute_channel_order: bool,
151 support_gpa_pinning: bool,
152}
153
154pub struct ServerWithNotifier<'a, T> {
155 inner: &'a mut Server,
156 notifier: &'a mut T,
157}
158
159impl<T> Drop for ServerWithNotifier<'_, T> {
160 fn drop(&mut self) {
161 self.inner.validate();
162 }
163}
164
165impl<T: Notifier> Inspect for ServerWithNotifier<'_, T> {
166 fn inspect(&self, req: inspect::Request<'_>) {
167 let mut resp = req.respond();
168 let (state, info, next_action) = match &self.inner.state {
169 ConnectionState::Disconnected => ("disconnected", None, None),
170 ConnectionState::Connecting { info, .. } => ("connecting", Some(info), None),
171 ConnectionState::Connected(info) => (
172 if info.offers_sent {
173 "connected"
174 } else {
175 "negotiated"
176 },
177 Some(info),
178 None,
179 ),
180 ConnectionState::Disconnecting { next_action, .. } => {
181 ("disconnecting", None, Some(next_action))
182 }
183 };
184
185 resp.field("connection_info", info);
186 let next_action = next_action.map(|a| match a {
187 ConnectionAction::None => "disconnect",
188 ConnectionAction::Reset => "reset",
189 ConnectionAction::SendUnloadComplete => "unload",
190 ConnectionAction::Reconnect { .. } => "reconnect",
191 ConnectionAction::SendFailedVersionResponse => "send_version_response",
192 });
193 resp.field("state", state)
194 .field("next_action", next_action)
195 .field(
196 "assigned_monitors_bitmap",
197 format_args!("{:x}", self.inner.assigned_monitors.bitmap()),
198 )
199 .child("channels", |req| {
200 let mut resp = req.respond();
201 self.inner
202 .channels
203 .inspect(self.notifier, self.inner.get_version(), &mut resp);
204 for ((gpadl_id, offer_id), gpadl) in &self.inner.gpadls {
205 let channel = &self.inner.channels[*offer_id];
206 resp.field(
207 &channel_inspect_path(
208 &channel.offer,
209 format_args!("/gpadls/{}", gpadl_id.0),
210 ),
211 gpadl,
212 );
213 }
214 });
215 }
216}
217
218#[derive(Debug, Copy, Clone, Inspect)]
220struct MonitorPageGpaInfo {
221 gpas: MonitorPageGpas,
222 server_allocated: bool,
223}
224
225impl MonitorPageGpaInfo {
226 fn from_guest_gpas(gpas: MonitorPageGpas) -> Self {
228 Self {
229 gpas,
230 server_allocated: false,
231 }
232 }
233
234 fn from_server_gpas(gpas: MonitorPageGpas) -> Self {
236 Self {
237 gpas,
238 server_allocated: true,
239 }
240 }
241}
242
243#[derive(Debug, Copy, Clone, Inspect)]
244struct ConnectionInfo {
245 version: VersionInfo,
246 trusted: bool,
249 offers_sent: bool,
250 interrupt_page: Option<u64>,
251 monitor_page: Option<MonitorPageGpaInfo>,
252 target_message_vp: u32,
253 modifying: bool,
254 client_id: Guid,
255 paused: bool,
256}
257
258#[derive(Debug)]
260enum ConnectionState {
261 Disconnected,
262 Disconnecting {
263 next_action: ConnectionAction,
264 modify_sent: bool,
265 },
266 Connecting {
267 info: ConnectionInfo,
268 next_action: ConnectionAction,
269 },
270 Connected(ConnectionInfo),
271}
272
273impl ConnectionState {
274 fn check_version(&self, min_version: Version) -> bool {
276 matches!(self, ConnectionState::Connected(info) if info.version.version >= min_version)
277 }
278
279 fn check_feature_flags(&self, flags: impl Fn(FeatureFlags) -> bool) -> bool {
282 matches!(self, ConnectionState::Connected(info) if flags(info.version.feature_flags))
283 }
284
285 fn get_version(&self) -> Option<VersionInfo> {
286 if let ConnectionState::Connected(info) = self {
287 Some(info.version)
288 } else {
289 None
290 }
291 }
292
293 fn get_connected_info(&self) -> Option<&ConnectionInfo> {
295 if let ConnectionState::Connected(info) = self {
296 Some(info)
297 } else {
298 None
299 }
300 }
301
302 fn is_trusted(&self) -> bool {
303 match self {
304 ConnectionState::Connected(info) => info.trusted,
305 ConnectionState::Connecting { info, .. } => info.trusted,
306 _ => false,
307 }
308 }
309
310 fn is_paused(&self) -> bool {
311 if let ConnectionState::Connected(info) = self {
312 info.paused
313 } else {
314 false
315 }
316 }
317}
318
319#[derive(Debug, Copy, Clone)]
320enum ConnectionAction {
321 None,
322 Reset,
323 SendUnloadComplete,
324 Reconnect {
325 initiate_contact: InitiateContactRequest,
326 },
327 SendFailedVersionResponse,
328}
329
330#[derive(PartialEq, Eq, Debug, Copy, Clone)]
331pub enum MonitorPageRequest {
332 None,
333 Some(MonitorPageGpas),
334 Invalid,
335}
336
337#[derive(PartialEq, Eq, Debug, Copy, Clone)]
338pub struct InitiateContactRequest {
339 pub version_requested: u32,
340 pub target_message_vp: u32,
341 pub monitor_page: MonitorPageRequest,
342 pub target_sint: u8,
343 pub target_vtl: u8,
344 pub feature_flags: u32,
345 pub interrupt_page: Option<u64>,
346 pub client_id: Guid,
347 pub trusted: bool,
348}
349
350#[derive(Debug, Copy, Clone)]
351pub struct OpenRequest {
352 pub open_id: u32,
353 pub ring_buffer_gpadl_id: GpadlId,
354 pub target_vp: Option<u32>,
355 pub downstream_ring_buffer_page_offset: u32,
356 pub user_data: UserDefinedData,
357 pub guest_specified_interrupt_info: Option<SignalInfo>,
358 pub flags: protocol::OpenChannelFlags,
359}
360
361#[derive(Debug, Copy, Clone, Eq, PartialEq)]
362pub enum Update<T: std::fmt::Debug + Copy + Clone> {
363 Unchanged,
364 Reset,
365 Set(T),
366}
367
368impl<T: std::fmt::Debug + Copy + Clone> From<Option<T>> for Update<T> {
369 fn from(value: Option<T>) -> Self {
370 match value {
371 None => Self::Reset,
372 Some(value) => Self::Set(value),
373 }
374 }
375}
376
377#[derive(Debug, Copy, Clone, Eq, PartialEq)]
378pub struct ModifyConnectionRequest {
379 pub version: Option<VersionInfo>,
380 pub monitor_page: Update<MonitorPageGpas>,
381 pub interrupt_page: Update<u64>,
382 pub target_message_vp: Option<u32>,
383 pub notify_relay: bool,
384}
385
386impl Default for ModifyConnectionRequest {
388 fn default() -> Self {
389 Self {
390 version: None,
391 monitor_page: Update::Unchanged,
392 interrupt_page: Update::Unchanged,
393 target_message_vp: None,
394 notify_relay: true,
395 }
396 }
397}
398
399impl From<protocol::ModifyConnection> for ModifyConnectionRequest {
400 fn from(value: protocol::ModifyConnection) -> Self {
401 let monitor_page = if value.parent_to_child_monitor_page_gpa != 0 {
402 Update::Set(MonitorPageGpas {
403 parent_to_child: value.parent_to_child_monitor_page_gpa,
404 child_to_parent: value.child_to_parent_monitor_page_gpa,
405 })
406 } else {
407 Update::Reset
408 };
409
410 Self {
411 monitor_page,
412 ..Default::default()
413 }
414 }
415}
416
417#[derive(Debug, Copy, Clone)]
419pub enum ModifyConnectionResponse {
420 Supported(
426 protocol::ConnectionState,
427 FeatureFlags,
428 Option<MonitorPageGpas>,
429 ),
430 Unsupported,
432 Modified(protocol::ConnectionState),
435}
436
437#[derive(Debug, Copy, Clone)]
438pub enum ModifyState {
439 NotModifying,
440 Modifying { pending_target_vp: Option<u32> },
441}
442
443impl ModifyState {
444 pub fn is_modifying(&self) -> bool {
445 matches!(self, ModifyState::Modifying { .. })
446 }
447}
448
449#[derive(Debug, Copy, Clone)]
450pub struct SignalInfo {
451 pub event_flag: u16,
452 pub connection_id: u32,
453}
454
455#[derive(Debug, Copy, Clone, PartialEq, Eq)]
456enum RestoreState {
457 New,
459 Restoring,
463 Unmatched,
466 Restored,
468}
469
470#[derive(Debug, Clone)]
472enum ChannelState {
473 ClientReleased,
477
478 Closed,
480
481 Opening {
484 request: OpenRequest,
485 reserved_state: Option<ReservedState>,
486 },
487
488 Open {
490 params: OpenRequest,
491 modify_state: ModifyState,
492 reserved_state: Option<ReservedState>,
493 },
494
495 Closing {
497 params: OpenRequest,
498 reserved_state: Option<ReservedState>,
499 },
500
501 ClosingReopen {
504 params: OpenRequest,
505 request: OpenRequest,
506 },
507
508 Revoked,
510
511 Reoffered,
514
515 ClosingClientRelease,
518
519 OpeningClientRelease,
522}
523
524impl ChannelState {
525 fn is_released(&self) -> bool {
528 match self {
529 ChannelState::Closed
530 | ChannelState::Opening { .. }
531 | ChannelState::Open { .. }
532 | ChannelState::Closing { .. }
533 | ChannelState::ClosingReopen { .. }
534 | ChannelState::Revoked
535 | ChannelState::Reoffered => false,
536
537 ChannelState::ClientReleased
538 | ChannelState::ClosingClientRelease
539 | ChannelState::OpeningClientRelease => true,
540 }
541 }
542
543 fn is_revoked(&self) -> bool {
545 match self {
546 ChannelState::Revoked | ChannelState::Reoffered => true,
547
548 ChannelState::ClientReleased
549 | ChannelState::Closed
550 | ChannelState::Opening { .. }
551 | ChannelState::Open { .. }
552 | ChannelState::Closing { .. }
553 | ChannelState::ClosingReopen { .. }
554 | ChannelState::ClosingClientRelease
555 | ChannelState::OpeningClientRelease => false,
556 }
557 }
558
559 fn is_reserved(&self) -> bool {
560 match self {
561 ChannelState::Open {
563 reserved_state: Some(_),
564 ..
565 }
566 | ChannelState::Opening {
567 reserved_state: Some(_),
568 ..
569 }
570 | ChannelState::Closing {
571 reserved_state: Some(_),
572 ..
573 } => true,
574
575 ChannelState::Opening { .. }
576 | ChannelState::Open { .. }
577 | ChannelState::Closing { .. }
578 | ChannelState::ClientReleased
579 | ChannelState::Closed
580 | ChannelState::ClosingReopen { .. }
581 | ChannelState::Revoked
582 | ChannelState::Reoffered
583 | ChannelState::ClosingClientRelease
584 | ChannelState::OpeningClientRelease => false,
585 }
586 }
587}
588
589impl Display for ChannelState {
590 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
591 let state = match self {
592 Self::ClientReleased => "ClientReleased",
593 Self::Closed => "Closed",
594 Self::Opening { .. } => "Opening",
595 Self::Open { .. } => "Open",
596 Self::Closing { .. } => "Closing",
597 Self::ClosingReopen { .. } => "ClosingReopen",
598 Self::Revoked => "Revoked",
599 Self::Reoffered => "Reoffered",
600 Self::ClosingClientRelease => "ClosingClientRelease",
601 Self::OpeningClientRelease => "OpeningClientRelease",
602 };
603 write!(f, "{}", state)
604 }
605}
606
607#[derive(Debug, Clone, Default, mesh::MeshPayload)]
609pub enum MnfUsage {
610 #[default]
612 Disabled,
613 Enabled { latency: Duration },
615 Relayed { monitor_id: u8 },
618}
619
620impl MnfUsage {
621 pub fn is_enabled(&self) -> bool {
622 matches!(self, Self::Enabled { .. })
623 }
624
625 pub fn is_relayed(&self) -> bool {
626 matches!(self, Self::Relayed { .. })
627 }
628
629 pub fn enabled_and_then<T>(&self, f: impl FnOnce(Duration) -> Option<T>) -> Option<T> {
630 if let Self::Enabled { latency } = self {
631 f(*latency)
632 } else {
633 None
634 }
635 }
636}
637
638impl From<Option<Duration>> for MnfUsage {
639 fn from(value: Option<Duration>) -> Self {
640 match value {
641 None => Self::Disabled,
642 Some(latency) => Self::Enabled { latency },
643 }
644 }
645}
646
647#[derive(Debug, Clone, Default, mesh::MeshPayload)]
648pub struct OfferParamsInternal {
649 pub interface_name: String,
651 pub instance_id: Guid,
652 pub interface_id: Guid,
653 pub mmio_megabytes: u16,
654 pub mmio_megabytes_optional: u16,
655 pub subchannel_index: u16,
656 pub use_mnf: MnfUsage,
657 pub offer_order: Option<u64>,
658 pub flags: OfferFlags,
659 pub user_defined: UserDefinedData,
660}
661
662impl OfferParamsInternal {
663 pub fn key(&self) -> OfferKey {
665 OfferKey {
666 interface_id: self.interface_id,
667 instance_id: self.instance_id,
668 subchannel_index: self.subchannel_index,
669 }
670 }
671}
672
673impl From<OfferParams> for OfferParamsInternal {
674 fn from(value: OfferParams) -> Self {
675 let mut user_defined = UserDefinedData::new_zeroed();
676
677 let mut flags = OfferFlags::new()
680 .with_confidential_ring_buffer(true)
681 .with_confidential_external_memory(value.allow_confidential_external_memory);
682
683 match value.channel_type {
684 ChannelType::Device { pipe_packets } => {
685 if pipe_packets {
686 flags.set_named_pipe_mode(true);
687 user_defined.as_pipe_params_mut().pipe_type = protocol::PipeType::MESSAGE;
688 }
689 }
690 ChannelType::Interface {
691 user_defined: interface_user_defined,
692 } => {
693 flags.set_enumerate_device_interface(true);
694 user_defined = interface_user_defined;
695 }
696 ChannelType::Pipe {
697 message_mode,
698 user_defined: pipe_user_defined,
699 pipe_flags,
700 } => {
701 flags.set_enumerate_device_interface(true);
702 flags.set_named_pipe_mode(true);
703 *user_defined.as_pipe_params_mut() = protocol::PipeUserDefinedParameters {
704 pipe_type: if message_mode {
705 protocol::PipeType::MESSAGE
706 } else {
707 protocol::PipeType::BYTE
708 },
709 user_defined: pipe_user_defined,
710 flags: pipe_flags,
711 };
712 }
713 ChannelType::HvSocket {
714 is_connect,
715 is_for_container,
716 silo_id,
717 } => {
718 flags.set_enumerate_device_interface(true);
719 flags.set_tlnpi_provider(true);
720 flags.set_named_pipe_mode(true);
721 *user_defined.as_hvsock_params_mut() = protocol::HvsockUserDefinedParameters::new(
722 is_connect,
723 is_for_container,
724 silo_id,
725 );
726 }
727 };
728
729 Self {
730 interface_name: value.interface_name,
731 instance_id: value.instance_id,
732 interface_id: value.interface_id,
733 mmio_megabytes: value.mmio_megabytes,
734 mmio_megabytes_optional: value.mmio_megabytes_optional,
735 subchannel_index: value.subchannel_index,
736 use_mnf: value.mnf_interrupt_latency.into(),
737 offer_order: value.offer_order,
738 user_defined,
739 flags,
740 }
741 }
742}
743
744#[derive(Debug, Copy, Clone, Inspect, PartialEq, Eq)]
745pub struct ConnectionTarget {
746 pub vp: u32,
747 pub sint: u8,
748}
749
750#[derive(Debug, Copy, Clone, PartialEq, Eq)]
751pub enum MessageTarget {
752 Default,
753 ReservedChannel(OfferId, ConnectionTarget),
754 Custom(ConnectionTarget),
755}
756
757impl MessageTarget {
758 pub fn for_offer(offer_id: OfferId, reserved_state: &Option<ReservedState>) -> Self {
759 if let Some(state) = reserved_state {
760 Self::ReservedChannel(offer_id, state.target)
761 } else {
762 Self::Default
763 }
764 }
765}
766
767#[derive(Debug, Copy, Clone)]
768pub struct ReservedState {
769 version: VersionInfo,
770 target: ConnectionTarget,
771}
772
773#[derive(Debug)]
775struct Channel {
776 info: Option<OfferedInfo>,
777 offer: OfferParamsInternal,
778 state: ChannelState,
779 restore_state: RestoreState,
780}
781
782#[derive(Debug, Copy, Clone)]
783struct OfferedInfo {
784 channel_id: ChannelId,
785 connection_id: u32,
786 monitor_id: Option<MonitorId>,
787}
788
789impl Channel {
790 fn inspect_state(&self, resp: &mut inspect::Response<'_>) {
791 let mut target_vp = None;
792 let mut event_flag = None;
793 let mut connection_id = None;
794 let mut reserved_target = None;
795 let state = match &self.state {
796 ChannelState::ClientReleased => "client_released",
797 ChannelState::Closed => "closed",
798 ChannelState::Opening { reserved_state, .. } => {
799 reserved_target = reserved_state.map(|state| state.target);
800 "opening"
801 }
802 ChannelState::Open {
803 params,
804 reserved_state,
805 ..
806 } => {
807 target_vp = Some(params.target_vp);
808 if let Some(id) = params.guest_specified_interrupt_info {
809 event_flag = Some(id.event_flag);
810 connection_id = Some(id.connection_id);
811 }
812 reserved_target = reserved_state.map(|state| state.target);
813 "open"
814 }
815 ChannelState::Closing { reserved_state, .. } => {
816 reserved_target = reserved_state.map(|state| state.target);
817 "closing"
818 }
819 ChannelState::ClosingReopen { .. } => "closing_reopen",
820 ChannelState::Revoked => "revoked",
821 ChannelState::Reoffered => "reoffered",
822 ChannelState::ClosingClientRelease => "closing_client_release",
823 ChannelState::OpeningClientRelease => "opening_client_release",
824 };
825 let restore_state = match self.restore_state {
826 RestoreState::New => "new",
827 RestoreState::Restoring => "restoring",
828 RestoreState::Restored => "restored",
829 RestoreState::Unmatched => "unmatched",
830 };
831 if let Some(info) = &self.info {
832 resp.field("channel_id", info.channel_id.0)
833 .field("offered_connection_id", info.connection_id)
834 .field("monitor_id", info.monitor_id.map(|id| id.0));
835 }
836 resp.field("state", state)
837 .field("restore_state", restore_state)
838 .field("interface_name", self.offer.interface_name.clone())
839 .display("instance_id", &self.offer.instance_id)
840 .display("interface_id", &self.offer.interface_id)
841 .field("mmio_megabytes", self.offer.mmio_megabytes)
842 .field("target_vp", target_vp)
843 .field("guest_specified_event_flag", event_flag)
844 .field("guest_specified_connection_id", connection_id)
845 .field("reserved_connection_target", reserved_target)
846 .binary("offer_flags", self.offer.flags.into_bits());
847 }
848
849 fn handled_monitor_info(&self) -> Option<MonitorInfo> {
859 self.offer.use_mnf.enabled_and_then(|latency| {
860 if self.state.is_reserved() {
861 None
862 } else {
863 self.info.and_then(|info| {
864 info.monitor_id.map(|monitor_id| MonitorInfo {
865 monitor_id,
866 latency,
867 })
868 })
869 }
870 })
871 }
872
873 fn prepare_channel(
876 &mut self,
877 offer_id: OfferId,
878 assigned_channels: &mut AssignedChannels,
879 assigned_monitors: &mut AssignedMonitors,
880 ) {
881 assert!(self.info.is_none());
882
883 let entry = assigned_channels
885 .allocate()
886 .expect("there are enough channel IDs for everything in ChannelList");
887
888 let channel_id = entry.id();
889 entry.insert(offer_id);
890 let connection_id = ConnectionId::new(channel_id.0, assigned_channels.vtl, VMBUS_SINT);
891
892 let monitor_id = match self.offer.use_mnf {
897 MnfUsage::Enabled { .. } => {
898 let monitor_id = assigned_monitors.assign_monitor();
899 if monitor_id.is_none() {
900 tracelimit::warn_ratelimited!("Out of monitor IDs.");
901 }
902
903 monitor_id
904 }
905 MnfUsage::Relayed { monitor_id } => Some(MonitorId(monitor_id)),
906 MnfUsage::Disabled => None,
907 };
908
909 self.info = Some(OfferedInfo {
910 channel_id,
911 connection_id: connection_id.0,
912 monitor_id,
913 });
914 }
915
916 fn release_channel(
918 &mut self,
919 offer_id: OfferId,
920 assigned_channels: &mut AssignedChannels,
921 assigned_monitors: &mut AssignedMonitors,
922 ) {
923 if let Some(info) = self.info.take() {
924 assigned_channels.free(info.channel_id, offer_id);
925
926 if let Some(monitor_id) = info.monitor_id {
928 if self.offer.use_mnf.is_enabled() {
929 assigned_monitors.release_monitor(monitor_id);
930 }
931 }
932 }
933 }
934}
935
936#[derive(Debug)]
937struct AssignedChannels {
938 assignments: Vec<Option<OfferId>>,
939 vtl: Vtl,
940 reserved_offset: usize,
941 count_in_reserved_range: usize,
943}
944
945impl AssignedChannels {
946 fn new(vtl: Vtl, channel_id_offset: u16) -> Self {
947 Self {
948 assignments: vec![None; MAX_CHANNELS],
949 vtl,
950 reserved_offset: channel_id_offset as usize,
951 count_in_reserved_range: 0,
952 }
953 }
954
955 fn allowable_channel_count(&self) -> usize {
956 MAX_CHANNELS - self.reserved_offset + self.count_in_reserved_range
957 }
958
959 fn get(&self, channel_id: ChannelId) -> Option<OfferId> {
960 self.assignments
961 .get(Self::index(channel_id))
962 .copied()
963 .flatten()
964 }
965
966 fn set(&mut self, channel_id: ChannelId) -> Result<AssignmentEntry<'_>, OfferError> {
967 let index = Self::index(channel_id);
968 if self
969 .assignments
970 .get(index)
971 .ok_or(OfferError::InvalidChannelId(channel_id))?
972 .is_some()
973 {
974 return Err(OfferError::ChannelIdInUse(channel_id));
975 }
976 Ok(AssignmentEntry { list: self, index })
977 }
978
979 fn allocate(&mut self) -> Option<AssignmentEntry<'_>> {
980 let index = self.reserved_offset
981 + self.assignments[self.reserved_offset..]
982 .iter()
983 .position(|x| x.is_none())?;
984 Some(AssignmentEntry { list: self, index })
985 }
986
987 fn free(&mut self, channel_id: ChannelId, offer_id: OfferId) {
988 let index = Self::index(channel_id);
989 let slot = &mut self.assignments[index];
990 assert_eq!(slot.take(), Some(offer_id));
991 if index < self.reserved_offset {
992 self.count_in_reserved_range -= 1;
993 }
994 }
995
996 fn index(channel_id: ChannelId) -> usize {
997 channel_id.0.wrapping_sub(1) as usize
998 }
999}
1000
1001struct AssignmentEntry<'a> {
1002 list: &'a mut AssignedChannels,
1003 index: usize,
1004}
1005
1006impl AssignmentEntry<'_> {
1007 pub fn id(&self) -> ChannelId {
1008 ChannelId(self.index as u32 + 1)
1009 }
1010
1011 pub fn insert(self, offer_id: OfferId) {
1012 assert!(
1013 self.list.assignments[self.index]
1014 .replace(offer_id)
1015 .is_none()
1016 );
1017
1018 if self.index < self.list.reserved_offset {
1019 self.list.count_in_reserved_range += 1;
1020 }
1021 }
1022}
1023
1024struct ChannelList {
1025 channels: Slab<Channel>,
1026}
1027
1028fn channel_inspect_path(offer: &OfferParamsInternal, suffix: std::fmt::Arguments<'_>) -> String {
1029 if offer.subchannel_index == 0 {
1030 format!("{}{}", offer.instance_id, suffix)
1031 } else {
1032 format!(
1033 "{}/subchannels/{}{}",
1034 offer.instance_id, offer.subchannel_index, suffix
1035 )
1036 }
1037}
1038
1039impl ChannelList {
1040 fn inspect(
1041 &self,
1042 notifier: &impl Notifier,
1043 version: Option<VersionInfo>,
1044 resp: &mut inspect::Response<'_>,
1045 ) {
1046 for (offer_id, channel) in self.iter() {
1047 resp.child(
1048 &channel_inspect_path(&channel.offer, format_args!("")),
1049 |req| {
1050 let mut resp = req.respond();
1051 channel.inspect_state(&mut resp);
1052
1053 resp.merge(inspect::adhoc(|req| {
1057 if !matches!(channel.state, ChannelState::Revoked) {
1058 notifier.inspect(version, offer_id, req);
1059 }
1060 }));
1061 },
1062 );
1063 }
1064 }
1065}
1066
1067pub const MAX_CHANNELS: usize = 2047;
1070
1071impl ChannelList {
1072 fn new() -> Self {
1073 Self {
1074 channels: Slab::new(),
1075 }
1076 }
1077
1078 fn len(&self) -> usize {
1080 self.channels.len()
1081 }
1082
1083 fn offer(&mut self, new_channel: Channel) -> OfferId {
1085 OfferId(self.channels.insert(new_channel))
1086 }
1087
1088 fn remove(&mut self, offer_id: OfferId) {
1090 let channel = self.channels.remove(offer_id.0);
1091 assert!(channel.info.is_none());
1092 }
1093
1094 fn get_by_channel_id_mut(
1099 &mut self,
1100 assigned_channels: &AssignedChannels,
1101 channel_id: ChannelId,
1102 ) -> Result<(OfferId, &mut Channel), ChannelError> {
1103 let offer_id = assigned_channels
1104 .get(channel_id)
1105 .ok_or(ChannelError::UnknownChannelId)?;
1106 let channel = &mut self[offer_id];
1107 if channel.state.is_released() {
1108 return Err(ChannelError::ChannelReleased);
1109 }
1110 assert_eq!(
1111 channel.info.as_ref().map(|info| info.channel_id),
1112 Some(channel_id)
1113 );
1114 Ok((offer_id, channel))
1115 }
1116
1117 fn get_by_channel_id(
1119 &self,
1120 assigned_channels: &AssignedChannels,
1121 channel_id: ChannelId,
1122 ) -> Result<(OfferId, &Channel), ChannelError> {
1123 let offer_id = assigned_channels
1124 .get(channel_id)
1125 .ok_or(ChannelError::UnknownChannelId)?;
1126 let channel = &self[offer_id];
1127 if channel.state.is_released() {
1128 return Err(ChannelError::ChannelReleased);
1129 }
1130 assert_eq!(
1131 channel.info.as_ref().map(|info| info.channel_id),
1132 Some(channel_id)
1133 );
1134 Ok((offer_id, channel))
1135 }
1136
1137 fn get_by_key_mut(&mut self, key: &OfferKey) -> Option<(OfferId, &mut Channel)> {
1140 for (offer_id, channel) in self.iter_mut() {
1141 if channel.offer.instance_id == key.instance_id
1142 && channel.offer.interface_id == key.interface_id
1143 && channel.offer.subchannel_index == key.subchannel_index
1144 {
1145 return Some((offer_id, channel));
1146 }
1147 }
1148 None
1149 }
1150
1151 fn iter(&self) -> impl Iterator<Item = (OfferId, &Channel)> {
1153 self.channels
1154 .iter()
1155 .map(|(id, channel)| (OfferId(id), channel))
1156 }
1157
1158 fn iter_mut(&mut self) -> impl Iterator<Item = (OfferId, &mut Channel)> {
1160 self.channels
1161 .iter_mut()
1162 .map(|(id, channel)| (OfferId(id), channel))
1163 }
1164
1165 fn retain<F>(&mut self, mut f: F)
1167 where
1168 F: FnMut(OfferId, &mut Channel) -> bool,
1169 {
1170 self.channels.retain(|id, channel| {
1171 let retain = f(OfferId(id), channel);
1172 if !retain {
1173 assert!(channel.info.is_none());
1174 }
1175 retain
1176 })
1177 }
1178}
1179
1180impl Index<OfferId> for ChannelList {
1181 type Output = Channel;
1182
1183 fn index(&self, offer_id: OfferId) -> &Self::Output {
1184 &self.channels[offer_id.0]
1185 }
1186}
1187
1188impl IndexMut<OfferId> for ChannelList {
1189 fn index_mut(&mut self, offer_id: OfferId) -> &mut Self::Output {
1190 &mut self.channels[offer_id.0]
1191 }
1192}
1193
1194#[derive(Debug, Inspect)]
1196struct Gpadl {
1197 count: u16,
1198 #[inspect(skip)]
1199 buf: Vec<u64>,
1200 state: GpadlState,
1201}
1202
1203#[derive(Debug, Copy, Clone, PartialEq, Eq, Inspect)]
1204enum GpadlState {
1205 InProgress,
1207 Offered,
1209 OfferedTearingDown,
1212 Accepted,
1214 TearingDown,
1216}
1217
1218impl Gpadl {
1219 fn new(count: u16, len: usize) -> Self {
1222 Self {
1223 state: GpadlState::InProgress,
1224 count,
1225 buf: Vec::with_capacity(len),
1226 }
1227 }
1228
1229 fn append(&mut self, data: &[u8]) -> Result<bool, ChannelError> {
1231 if self.state == GpadlState::InProgress {
1232 let buf = &mut self.buf;
1233 let len = min(data.len() & !7, (buf.capacity() - buf.len()) * 8);
1238 let data = &data[..len];
1239 let start = buf.len();
1240 buf.resize(buf.len() + data.len() / 8, 0);
1241 buf[start..].as_mut_bytes().copy_from_slice(data);
1242 Ok(if buf.len() == buf.capacity() {
1243 gparange::validate_gpa_ranges(self.count as usize, buf)
1244 .map_err(ChannelError::InvalidGpaRange)?;
1245 self.state = GpadlState::Offered;
1246 true
1247 } else {
1248 false
1249 })
1250 } else {
1251 Err(ChannelError::GpadlAlreadyComplete)
1252 }
1253 }
1254}
1255
1256#[derive(Debug, Copy, Clone)]
1258pub struct OpenParams {
1259 pub open_data: OpenData,
1260 pub connection_id: u32,
1261 pub event_flag: u16,
1262 pub monitor_info: Option<MonitorInfo>,
1263 pub flags: protocol::OpenChannelFlags,
1264 pub reserved_target: Option<ConnectionTarget>,
1265 pub channel_id: ChannelId,
1266}
1267
1268impl OpenParams {
1269 fn from_request(
1270 info: &OfferedInfo,
1271 request: &OpenRequest,
1272 monitor_info: Option<MonitorInfo>,
1273 reserved_target: Option<ConnectionTarget>,
1274 ) -> Self {
1275 let (event_flag, connection_id) = if let Some(id) = request.guest_specified_interrupt_info {
1278 (id.event_flag, id.connection_id)
1279 } else {
1280 (info.channel_id.0 as u16, info.connection_id)
1281 };
1282
1283 Self {
1284 open_data: OpenData {
1285 target_vp: request.target_vp,
1286 ring_offset: request.downstream_ring_buffer_page_offset,
1287 ring_gpadl_id: request.ring_buffer_gpadl_id,
1288 user_data: request.user_data,
1289 event_flag,
1290 connection_id,
1291 },
1292 connection_id,
1293 event_flag,
1294 monitor_info: request.target_vp.and(monitor_info),
1296 flags: request.flags.with_unused(0),
1297 reserved_target,
1298 channel_id: info.channel_id,
1299 }
1300 }
1301}
1302
1303#[derive(Debug)]
1305pub enum Action {
1306 Open(OpenParams, VersionInfo),
1307 Close,
1308 Gpadl(GpadlId, u16, Vec<u64>),
1309 TeardownGpadl {
1310 gpadl_id: GpadlId,
1311 post_restore: bool,
1312 },
1313 Modify {
1314 target_vp: u32,
1315 },
1316}
1317
1318static SUPPORTED_VERSIONS: &[Version] = &[
1320 Version::V1,
1321 Version::Win7,
1322 Version::Win8,
1323 Version::Win8_1,
1324 Version::Win10,
1325 Version::Win10Rs3_0,
1326 Version::Win10Rs3_1,
1327 Version::Win10Rs4,
1328 Version::Win10Rs5,
1329 Version::Iron,
1330 Version::Copper,
1331];
1332
1333const SUPPORTED_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
1337 .with_guest_specified_signal_parameters(true)
1338 .with_channel_interrupt_redirection(true)
1339 .with_modify_connection(true)
1340 .with_client_id(true)
1341 .with_pause_resume(true)
1342 .with_server_specified_monitor_pages(true);
1343
1344pub trait Notifier: Send {
1346 fn notify(&mut self, offer_id: OfferId, action: Action);
1348
1349 fn forward_unhandled(&mut self, request: InitiateContactRequest);
1351
1352 fn modify_connection(&mut self, request: ModifyConnectionRequest) -> anyhow::Result<()>;
1358
1359 fn inspect(&self, version: Option<VersionInfo>, offer_id: OfferId, req: inspect::Request<'_>) {
1361 let _ = (version, offer_id, req);
1362 }
1363
1364 #[must_use]
1367 fn send_message(&mut self, message: &OutgoingMessage, target: MessageTarget) -> bool;
1368
1369 fn notify_hvsock(&mut self, request: &HvsockConnectRequest);
1371
1372 fn reset_complete(&mut self);
1374
1375 fn unload_complete(&mut self);
1377}
1378
1379impl Server {
1380 pub fn new(
1382 vtl: Vtl,
1383 child_connection_id: u32,
1384 channel_id_offset: u16,
1385 use_absolute_channel_order: bool,
1386 support_gpa_pinning: bool,
1387 ) -> Self {
1388 Server {
1389 state: ConnectionState::Disconnected,
1390 channels: ChannelList::new(),
1391 assigned_channels: AssignedChannels::new(vtl, channel_id_offset),
1392 assigned_monitors: AssignedMonitors::new(),
1393 gpadls: Default::default(),
1394 incomplete_gpadls: Default::default(),
1395 child_connection_id,
1396 max_version: None,
1397 delayed_max_version: None,
1398 max_restore_version: None,
1399 pending_messages: PendingMessages(VecDeque::new()),
1400 require_server_allocated_mnf: false,
1401 use_absolute_channel_order,
1402 support_gpa_pinning,
1403 }
1404 }
1405
1406 pub fn with_notifier<'a, T: Notifier>(
1408 &'a mut self,
1409 notifier: &'a mut T,
1410 ) -> ServerWithNotifier<'a, T> {
1411 self.validate();
1412 ServerWithNotifier {
1413 inner: self,
1414 notifier,
1415 }
1416 }
1417
1418 pub fn set_require_server_allocated_mnf(&mut self, require: bool) {
1421 self.require_server_allocated_mnf = require;
1422 }
1423
1424 fn validate(&self) {
1425 #[cfg(debug_assertions)]
1426 for (_, channel) in self.channels.iter() {
1427 let should_have_info = !channel.state.is_released();
1428 if channel.info.is_some() != should_have_info {
1429 panic!("channel invariant violation: {channel:?}");
1430 }
1431 }
1432 }
1433
1434 pub fn set_compatibility_version(&mut self, version: MaxVersionInfo, delay: bool) {
1439 if delay {
1440 self.delayed_max_version = Some(version)
1441 } else {
1442 tracing::info!(?version, "Limiting VmBus connections to version");
1443 self.max_version = Some(version);
1444 }
1445 }
1446
1447 pub fn set_restore_compatibility_version(&mut self, version: MaxVersionInfo) {
1455 tracing::info!(?version, "Limiting VmBus restore to version");
1456 self.max_restore_version = Some(version);
1457 }
1458
1459 pub fn channel_gpadls(&self, offer_id: OfferId) -> Vec<RestoredGpadl> {
1460 self.gpadls
1461 .iter()
1462 .filter_map(|(&(gpadl_id, gpadl_offer_id), gpadl)| {
1463 if offer_id != gpadl_offer_id {
1464 return None;
1465 }
1466 let accepted = match gpadl.state {
1467 GpadlState::Offered | GpadlState::OfferedTearingDown => false,
1468 GpadlState::Accepted => true,
1469 GpadlState::InProgress | GpadlState::TearingDown => return None,
1470 };
1471 Some(RestoredGpadl {
1472 request: GpadlRequest {
1473 id: gpadl_id,
1474 count: gpadl.count,
1475 buf: gpadl.buf.clone(),
1476 },
1477 accepted,
1478 })
1479 })
1480 .collect()
1481 }
1482
1483 pub fn get_version(&self) -> Option<VersionInfo> {
1484 self.state.get_version()
1485 }
1486
1487 pub fn get_restore_open_params(&self, offer_id: OfferId) -> Result<OpenParams, RestoreError> {
1488 let channel = &self.channels[offer_id];
1489
1490 match channel.restore_state {
1492 RestoreState::New => {
1493 return Err(RestoreError::MissingChannel(channel.offer.key()));
1497 }
1498 RestoreState::Restoring => {}
1499 RestoreState::Unmatched => unreachable!(),
1500 RestoreState::Restored => {
1501 return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1502 }
1503 }
1504
1505 let info = channel
1506 .info
1507 .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1508
1509 let (request, reserved_state) = match channel.state {
1510 ChannelState::Closed => {
1511 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1512 }
1513 ChannelState::Closing { params, .. } | ChannelState::ClosingReopen { params, .. } => {
1514 (params, None)
1515 }
1516 ChannelState::Opening {
1517 request,
1518 reserved_state,
1519 } => (request, reserved_state),
1520 ChannelState::Open {
1521 params,
1522 reserved_state,
1523 ..
1524 } => (params, reserved_state),
1525 ChannelState::ClientReleased | ChannelState::Reoffered => {
1526 return Err(RestoreError::MissingChannel(channel.offer.key()));
1527 }
1528 ChannelState::Revoked
1529 | ChannelState::ClosingClientRelease
1530 | ChannelState::OpeningClientRelease => unreachable!(),
1531 };
1532
1533 Ok(OpenParams::from_request(
1534 &info,
1535 &request,
1536 channel.handled_monitor_info(),
1537 reserved_state.map(|state| state.target),
1538 ))
1539 }
1540
1541 pub fn has_pending_messages(&self) -> bool {
1543 !self.pending_messages.0.is_empty() && !self.state.is_paused()
1544 }
1545
1546 pub fn poll_flush_pending_messages(
1548 &mut self,
1549 mut send: impl FnMut(&OutgoingMessage) -> Poll<()>,
1550 ) -> Poll<()> {
1551 if !self.state.is_paused() {
1552 while let Some(message) = self.pending_messages.0.front() {
1553 ready!(send(message));
1554 self.pending_messages.0.pop_front();
1555 }
1556 }
1557
1558 Poll::Ready(())
1559 }
1560}
1561
1562impl<'a, N: 'a + Notifier> ServerWithNotifier<'a, N> {
1563 pub fn restore_channel(&mut self, offer_id: OfferId, open: bool) -> Result<(), RestoreError> {
1569 let channel = &mut self.inner.channels[offer_id];
1570
1571 match channel.restore_state {
1574 RestoreState::New => {
1575 if open {
1579 return Err(RestoreError::MissingChannel(channel.offer.key()));
1580 } else {
1581 return Ok(());
1582 }
1583 }
1584 RestoreState::Restoring => {}
1585 RestoreState::Unmatched => unreachable!(),
1586 RestoreState::Restored => {
1587 return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1588 }
1589 }
1590
1591 let info = channel
1592 .info
1593 .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1594
1595 if let Some(monitor_info) = channel.handled_monitor_info() {
1596 if !self
1597 .inner
1598 .assigned_monitors
1599 .claim_monitor(monitor_info.monitor_id)
1600 {
1601 return Err(RestoreError::DuplicateMonitorId(monitor_info.monitor_id.0));
1602 }
1603 }
1604
1605 if open {
1606 match channel.state {
1607 ChannelState::Closed => {
1608 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1609 }
1610 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
1611 self.notifier.notify(offer_id, Action::Close);
1612 }
1613 ChannelState::Opening {
1614 request,
1615 reserved_state,
1616 } => {
1617 self.inner
1618 .pending_messages
1619 .sender(self.notifier, self.inner.state.is_paused())
1620 .send_open_result(
1621 info.channel_id,
1622 &request,
1623 protocol::STATUS_SUCCESS,
1624 MessageTarget::for_offer(offer_id, &reserved_state),
1625 );
1626 channel.state = ChannelState::Open {
1627 params: request,
1628 modify_state: ModifyState::NotModifying,
1629 reserved_state,
1630 };
1631 }
1632 ChannelState::Open { .. } => {}
1633 ChannelState::ClientReleased | ChannelState::Reoffered => {
1634 return Err(RestoreError::MissingChannel(channel.offer.key()));
1635 }
1636 ChannelState::Revoked
1637 | ChannelState::ClosingClientRelease
1638 | ChannelState::OpeningClientRelease => unreachable!(),
1639 };
1640 } else {
1641 match channel.state {
1642 ChannelState::Closed => {}
1643 ChannelState::Reoffered => {}
1648 ChannelState::Closing { .. } => {
1649 channel.state = ChannelState::Closed;
1650 }
1651 ChannelState::ClosingReopen { request, .. } => {
1652 self.notifier.notify(
1653 offer_id,
1654 Action::Open(
1655 OpenParams::from_request(
1656 &info,
1657 &request,
1658 channel.handled_monitor_info(),
1659 None,
1660 ),
1661 self.inner.state.get_version().expect("must be connected"),
1662 ),
1663 );
1664 channel.state = ChannelState::Opening {
1665 request,
1666 reserved_state: None,
1667 };
1668 }
1669 ChannelState::Opening {
1670 request,
1671 reserved_state,
1672 } => {
1673 self.notifier.notify(
1674 offer_id,
1675 Action::Open(
1676 OpenParams::from_request(
1677 &info,
1678 &request,
1679 channel.handled_monitor_info(),
1680 reserved_state.map(|state| state.target),
1681 ),
1682 self.inner.state.get_version().expect("must be connected"),
1683 ),
1684 );
1685 }
1686 ChannelState::Open { .. } => {
1687 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1688 }
1689 ChannelState::ClientReleased => {
1690 return Err(RestoreError::MissingChannel(channel.offer.key()));
1691 }
1692 ChannelState::Revoked
1693 | ChannelState::ClosingClientRelease
1694 | ChannelState::OpeningClientRelease => unreachable!(),
1695 }
1696 }
1697
1698 channel.restore_state = RestoreState::Restored;
1699 Ok(())
1700 }
1701
1702 pub fn revoke_unclaimed_channels(&mut self) {
1705 for (offer_id, channel) in self.inner.channels.iter_mut() {
1706 match channel.restore_state {
1707 RestoreState::Restored => {
1708 }
1710 RestoreState::New => {
1711 if let ConnectionState::Connected(info) = &self.inner.state {
1716 if info.offers_sent && matches!(channel.state, ChannelState::ClientReleased)
1717 {
1718 channel.prepare_channel(
1719 offer_id,
1720 &mut self.inner.assigned_channels,
1721 &mut self.inner.assigned_monitors,
1722 );
1723 channel.state = ChannelState::Closed;
1724 self.inner
1725 .pending_messages
1726 .sender(self.notifier, self.inner.state.is_paused())
1727 .send_offer(channel, info);
1728 }
1729 }
1730 }
1731 RestoreState::Restoring => {
1732 let retain = revoke(
1736 self.inner
1737 .pending_messages
1738 .sender(self.notifier, self.inner.state.is_paused()),
1739 offer_id,
1740 channel,
1741 &mut self.inner.gpadls,
1742 );
1743 assert!(retain, "channel has not been released");
1744 channel.state = ChannelState::Reoffered;
1745 }
1746 RestoreState::Unmatched => {
1747 let retain = revoke(
1750 self.inner
1751 .pending_messages
1752 .sender(self.notifier, self.inner.state.is_paused()),
1753 offer_id,
1754 channel,
1755 &mut self.inner.gpadls,
1756 );
1757 assert!(retain, "channel has not been released");
1758 }
1759 }
1760 }
1761
1762 for (&(gpadl_id, offer_id), gpadl) in self.inner.gpadls.iter_mut() {
1764 match gpadl.state {
1765 GpadlState::InProgress | GpadlState::Accepted => {}
1766 GpadlState::Offered => {
1767 self.notifier.notify(
1768 offer_id,
1769 Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
1770 );
1771 }
1772 GpadlState::TearingDown => {
1773 self.notifier.notify(
1774 offer_id,
1775 Action::TeardownGpadl {
1776 gpadl_id,
1777 post_restore: true,
1778 },
1779 );
1780 }
1781 GpadlState::OfferedTearingDown => unreachable!(),
1782 }
1783 }
1784
1785 self.check_disconnected();
1786 }
1787
1788 pub fn reset(&mut self) {
1793 assert!(!self.is_resetting());
1794 if self.request_disconnect(ConnectionAction::Reset) {
1795 self.complete_reset();
1796 }
1797 }
1798
1799 fn complete_reset(&mut self) {
1800 for (_, channel) in self.inner.channels.iter_mut() {
1802 channel.restore_state = RestoreState::New;
1803 }
1804 self.inner.pending_messages.0.clear();
1805 self.notifier.reset_complete();
1806 }
1807
1808 pub fn offer_channel(&mut self, offer: OfferParamsInternal) -> Result<OfferId, OfferError> {
1810 if let Some((offer_id, channel)) = self.inner.channels.get_by_key_mut(&offer.key()) {
1812 if channel.restore_state != RestoreState::Unmatched
1816 && !matches!(channel.state, ChannelState::Revoked)
1817 {
1818 return Err(OfferError::AlreadyExists(offer.key()));
1819 }
1820
1821 let info = channel.info.expect("assigned");
1822 if channel.restore_state == RestoreState::Unmatched {
1823 tracing::debug!(
1824 offer_id = offer_id.0,
1825 key = %channel.offer.key(),
1826 "matched channel"
1827 );
1828
1829 assert!(!matches!(channel.state, ChannelState::Revoked));
1830 channel.restore_state = RestoreState::Restoring;
1834
1835 if let MnfUsage::Relayed { monitor_id } = offer.use_mnf {
1838 if info.monitor_id != Some(MonitorId(monitor_id)) {
1839 return Err(OfferError::MismatchedMonitorId(
1840 info.monitor_id,
1841 MonitorId(monitor_id),
1842 ));
1843 }
1844 }
1845 } else {
1846 channel.state = ChannelState::Reoffered;
1850 tracing::info!(?offer_id, key = %channel.offer.key(), "channel marked for reoffer");
1851 }
1852
1853 channel.offer = offer;
1854 return Ok(offer_id);
1855 }
1856
1857 let mut connected_info = None;
1858 let state = match &self.inner.state {
1859 ConnectionState::Connected(info) => {
1860 if info.offers_sent {
1861 connected_info = Some(info);
1862 ChannelState::Closed
1863 } else {
1864 ChannelState::ClientReleased
1865 }
1866 }
1867 ConnectionState::Connecting { .. }
1868 | ConnectionState::Disconnecting { .. }
1869 | ConnectionState::Disconnected => ChannelState::ClientReleased,
1870 };
1871
1872 if self.inner.channels.len() >= self.inner.assigned_channels.allowable_channel_count() {
1874 return Err(OfferError::TooManyChannels);
1875 }
1876
1877 let key = offer.key();
1878 let confidential_ring_buffer = offer.flags.confidential_ring_buffer();
1879 let confidential_external_memory = offer.flags.confidential_external_memory();
1880 let channel = Channel {
1881 info: None,
1882 offer,
1883 state,
1884 restore_state: RestoreState::New,
1885 };
1886
1887 let offer_id = self.inner.channels.offer(channel);
1888 if let Some(info) = connected_info {
1889 let channel = &mut self.inner.channels[offer_id];
1890 channel.prepare_channel(
1891 offer_id,
1892 &mut self.inner.assigned_channels,
1893 &mut self.inner.assigned_monitors,
1894 );
1895
1896 self.inner
1897 .pending_messages
1898 .sender(self.notifier, self.inner.state.is_paused())
1899 .send_offer(channel, info);
1900 }
1901
1902 tracing::info!(?offer_id, %key, confidential_ring_buffer, confidential_external_memory, "new channel");
1903 Ok(offer_id)
1904 }
1905
1906 pub fn revoke_channel(&mut self, offer_id: OfferId) {
1908 let channel = &mut self.inner.channels[offer_id];
1909 let retain = revoke(
1910 self.inner
1911 .pending_messages
1912 .sender(self.notifier, self.inner.state.is_paused()),
1913 offer_id,
1914 channel,
1915 &mut self.inner.gpadls,
1916 );
1917 if !retain {
1918 self.inner.channels.remove(offer_id);
1919 }
1920
1921 self.check_disconnected();
1922 }
1923
1924 pub fn open_complete(&mut self, offer_id: OfferId, result: i32) {
1926 let channel = &mut self.inner.channels[offer_id];
1927 tracing::debug!(offer_id = offer_id.0, key = %channel.offer.key(), result, "open complete");
1928
1929 match channel.state {
1930 ChannelState::Opening {
1931 request,
1932 reserved_state,
1933 } => {
1934 let channel_id = channel.info.expect("assigned").channel_id;
1935 if result >= 0 {
1936 tracelimit::info_ratelimited!(
1937 offer_id = offer_id.0,
1938 channel_id = channel_id.0,
1939 key = %channel.offer.key(),
1940 result,
1941 "opened channel"
1942 );
1943 } else {
1944 tracelimit::error_ratelimited!(
1946 offer_id = offer_id.0,
1947 channel_id = channel_id.0,
1948 key = %channel.offer.key(),
1949 result,
1950 "failed to open channel"
1951 );
1952 }
1953
1954 self.inner
1955 .pending_messages
1956 .sender(self.notifier, self.inner.state.is_paused())
1957 .send_open_result(
1958 channel_id,
1959 &request,
1960 result,
1961 MessageTarget::for_offer(offer_id, &reserved_state),
1962 );
1963 channel.state = if result >= 0 {
1964 ChannelState::Open {
1965 params: request,
1966 modify_state: ModifyState::NotModifying,
1967 reserved_state,
1968 }
1969 } else {
1970 ChannelState::Closed
1971 };
1972 }
1973 ChannelState::OpeningClientRelease => {
1974 tracing::info!(
1975 offer_id = offer_id.0,
1976 key = %channel.offer.key(),
1977 result,
1978 "opened channel (client released)"
1979 );
1980
1981 if result >= 0 {
1982 channel.state = ChannelState::ClosingClientRelease;
1983 self.notifier.notify(offer_id, Action::Close);
1984 } else {
1985 channel.state = ChannelState::ClientReleased;
1986 self.check_disconnected();
1987 }
1988 }
1989
1990 ChannelState::ClientReleased
1991 | ChannelState::Closed
1992 | ChannelState::Open { .. }
1993 | ChannelState::Closing { .. }
1994 | ChannelState::ClosingReopen { .. }
1995 | ChannelState::Revoked
1996 | ChannelState::Reoffered
1997 | ChannelState::ClosingClientRelease => {
1998 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid open complete")
1999 }
2000 }
2001 }
2002
2003 fn are_channels_reset(&self, include_reserved: bool) -> bool {
2006 self.inner.gpadls.keys().all(|(_, offer_id)| {
2007 !include_reserved && self.inner.channels[*offer_id].state.is_reserved()
2008 }) && self.inner.channels.iter().all(|(_, channel)| {
2009 matches!(channel.state, ChannelState::ClientReleased)
2010 || (!include_reserved && channel.state.is_reserved())
2011 })
2012 }
2013
2014 fn check_disconnected(&mut self) {
2018 match self.inner.state {
2019 ConnectionState::Disconnecting {
2020 next_action,
2021 modify_sent: false,
2022 } => {
2023 if self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)) {
2024 self.notify_disconnect(next_action);
2025 }
2026 }
2027 ConnectionState::Disconnecting {
2028 modify_sent: true, ..
2029 }
2030 | ConnectionState::Disconnected
2031 | ConnectionState::Connected { .. }
2032 | ConnectionState::Connecting { .. } => (),
2033 }
2034 }
2035
2036 fn notify_disconnect(&mut self, next_action: ConnectionAction) {
2038 debug_assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2040 self.inner.state = ConnectionState::Disconnecting {
2041 next_action,
2042 modify_sent: true,
2043 };
2044
2045 self.notifier
2047 .modify_connection(ModifyConnectionRequest {
2048 monitor_page: Update::Reset,
2049 interrupt_page: Update::Reset,
2050 ..Default::default()
2051 })
2052 .expect("resetting state should not fail");
2053 }
2054
2055 fn is_resetting(&self) -> bool {
2058 matches!(
2059 &self.inner.state,
2060 ConnectionState::Connecting {
2061 next_action: ConnectionAction::Reset,
2062 ..
2063 } | ConnectionState::Disconnecting {
2064 next_action: ConnectionAction::Reset,
2065 ..
2066 }
2067 )
2068 }
2069
2070 pub fn close_complete(&mut self, offer_id: OfferId) {
2072 let channel = &mut self.inner.channels[offer_id];
2073 tracing::info!(offer_id = offer_id.0, key = %channel.offer.key(), "closed channel");
2074 match channel.state {
2075 ChannelState::Closing {
2076 reserved_state: Some(reserved_state),
2077 ..
2078 } => {
2079 channel.state = ChannelState::Closed;
2080 let channel_id = channel.info.expect("assigned").channel_id;
2081 self.send_close_reserved_channel_response(
2085 channel_id,
2086 offer_id,
2087 reserved_state.target,
2088 );
2089
2090 if !matches!(self.inner.state, ConnectionState::Connected { .. }) {
2091 let channel = &mut self.inner.channels[offer_id];
2093 if Self::client_release_channel(
2096 self.inner
2097 .pending_messages
2098 .sender(self.notifier, self.inner.state.is_paused()),
2099 offer_id,
2100 channel,
2101 &mut self.inner.gpadls,
2102 &mut self.inner.incomplete_gpadls,
2103 &mut self.inner.assigned_channels,
2104 &mut self.inner.assigned_monitors,
2105 None,
2106 false,
2107 ) {
2108 self.inner.channels.remove(offer_id);
2109 }
2110 }
2111 }
2112 ChannelState::Closing { .. } => {
2113 channel.state = ChannelState::Closed;
2114 }
2115 ChannelState::ClosingClientRelease => {
2116 channel.state = ChannelState::ClientReleased;
2117 self.check_disconnected();
2118 }
2119 ChannelState::ClosingReopen { request, .. } => {
2120 channel.state = ChannelState::Closed;
2121 self.open_channel(offer_id, &request, None);
2122 }
2123
2124 ChannelState::Closed
2125 | ChannelState::ClientReleased
2126 | ChannelState::Opening { .. }
2127 | ChannelState::Open { .. }
2128 | ChannelState::Revoked
2129 | ChannelState::Reoffered
2130 | ChannelState::OpeningClientRelease => {
2131 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid close complete")
2132 }
2133 }
2134 }
2135
2136 fn send_close_reserved_channel_response(
2137 &mut self,
2138 channel_id: ChannelId,
2139 offer_id: OfferId,
2140 target: ConnectionTarget,
2141 ) {
2142 self.sender().send_message_with_target(
2143 &protocol::CloseReservedChannelResponse { channel_id },
2144 MessageTarget::ReservedChannel(offer_id, target),
2145 );
2146 }
2147
2148 fn handle_initiate_contact(
2151 &mut self,
2152 input: &protocol::InitiateContact2,
2153 message: &SynicMessage,
2154 includes_client_id: bool,
2155 ) -> Result<(), ChannelError> {
2156 let target_info =
2157 protocol::TargetInfo::from(input.initiate_contact.interrupt_page_or_target_info);
2158
2159 let target_sint = if message.multiclient
2160 && input.initiate_contact.version_requested >= Version::Win10Rs3_1 as u32
2161 {
2162 target_info.sint()
2163 } else {
2164 VMBUS_SINT
2165 };
2166
2167 let target_vtl = if message.multiclient
2168 && input.initiate_contact.version_requested >= Version::Win10Rs4 as u32
2169 {
2170 target_info.vtl()
2171 } else {
2172 0
2173 };
2174
2175 let feature_flags = if input.initiate_contact.version_requested >= Version::Copper as u32 {
2176 target_info.feature_flags()
2177 } else {
2178 0
2179 };
2180
2181 let target_message_vp =
2186 if input.initiate_contact.version_requested >= Version::Win8_1 as u32 {
2187 input.initiate_contact.target_message_vp
2188 } else {
2189 0
2190 };
2191
2192 let interrupt_page = (input.initiate_contact.version_requested < Version::Win8 as u32
2199 && input.initiate_contact.interrupt_page_or_target_info != 0)
2200 .then_some(input.initiate_contact.interrupt_page_or_target_info);
2201
2202 let monitor_page = if (input.initiate_contact.parent_to_child_monitor_page_gpa == 0)
2205 != (input.initiate_contact.child_to_parent_monitor_page_gpa == 0)
2206 {
2207 MonitorPageRequest::Invalid
2208 } else if input.initiate_contact.parent_to_child_monitor_page_gpa != 0 {
2209 MonitorPageRequest::Some(MonitorPageGpas {
2210 parent_to_child: input.initiate_contact.parent_to_child_monitor_page_gpa,
2211 child_to_parent: input.initiate_contact.child_to_parent_monitor_page_gpa,
2212 })
2213 } else {
2214 MonitorPageRequest::None
2215 };
2216
2217 let client_id = if FeatureFlags::from(feature_flags).client_id() {
2220 if includes_client_id {
2221 input.client_id
2222 } else {
2223 return Err(ChannelError::ParseError(
2224 protocol::ParseError::MessageTooSmall(Some(
2225 protocol::MessageType::INITIATE_CONTACT,
2226 )),
2227 ));
2228 }
2229 } else {
2230 Guid::ZERO
2231 };
2232
2233 let request = InitiateContactRequest {
2234 version_requested: input.initiate_contact.version_requested,
2235 target_message_vp,
2236 monitor_page,
2237 target_sint,
2238 target_vtl,
2239 feature_flags,
2240 interrupt_page,
2241 client_id,
2242 trusted: message.trusted,
2243 };
2244 self.initiate_contact(request);
2245 Ok(())
2246 }
2247
2248 pub fn initiate_contact(&mut self, request: InitiateContactRequest) {
2249 let vtl = self.inner.assigned_channels.vtl as u8;
2252 if request.target_vtl != vtl {
2253 self.notifier.forward_unhandled(request);
2255 return;
2256 }
2257
2258 if request.target_sint != VMBUS_SINT {
2259 tracelimit::warn_ratelimited!(
2260 target_vtl = request.target_vtl,
2261 target_sint = request.target_sint,
2262 version = request.version_requested,
2263 "unsupported multiclient request",
2264 );
2265
2266 self.send_version_response_with_target(
2268 None,
2269 MessageTarget::Custom(ConnectionTarget {
2270 vp: request.target_message_vp,
2271 sint: request.target_sint,
2272 }),
2273 );
2274
2275 return;
2276 }
2277
2278 if !self.request_disconnect(ConnectionAction::Reconnect {
2279 initiate_contact: request,
2280 }) {
2281 return;
2282 }
2283
2284 let Some(version) = self.check_version_supported(&request) else {
2285 tracelimit::warn_ratelimited!(
2286 vtl,
2287 version = request.version_requested,
2288 client_id = ?request.client_id,
2289 "Guest requested unsupported version"
2290 );
2291
2292 self.send_version_response(None);
2294 return;
2295 };
2296
2297 let monitor_page = match request.monitor_page {
2300 MonitorPageRequest::Some(mp) => {
2301 if self.inner.require_server_allocated_mnf {
2302 if !version.feature_flags.server_specified_monitor_pages() {
2303 tracelimit::warn_ratelimited!(
2304 "guest-supplied monitor pages not supported; MNF will be disabled"
2305 );
2306 }
2307
2308 None
2309 } else {
2310 Some(mp)
2311 }
2312 }
2313 MonitorPageRequest::None => None,
2314 MonitorPageRequest::Invalid => {
2315 self.send_version_response(Some(VersionResponseData::new(
2317 version,
2318 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2319 )));
2320
2321 return;
2322 }
2323 };
2324
2325 self.inner.state = ConnectionState::Connecting {
2326 info: ConnectionInfo {
2327 version,
2328 trusted: request.trusted,
2329 interrupt_page: request.interrupt_page,
2330 monitor_page: monitor_page.map(MonitorPageGpaInfo::from_guest_gpas),
2331 target_message_vp: request.target_message_vp,
2332 modifying: false,
2333 offers_sent: false,
2334 client_id: request.client_id,
2335 paused: false,
2336 },
2337 next_action: ConnectionAction::None,
2338 };
2339
2340 if let Err(err) = self.notifier.modify_connection(ModifyConnectionRequest {
2343 version: Some(version),
2344 monitor_page: monitor_page.into(),
2345 interrupt_page: request.interrupt_page.into(),
2346 target_message_vp: Some(request.target_message_vp),
2347 notify_relay: true,
2348 }) {
2349 tracelimit::error_ratelimited!(?err, "server failed to change state");
2350 self.inner.state = ConnectionState::Disconnected;
2351 self.send_version_response(Some(VersionResponseData::new(
2352 version,
2353 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2354 )));
2355 }
2356 }
2357
2358 pub(crate) fn complete_initiate_contact(&mut self, response: ModifyConnectionResponse) {
2359 let ConnectionState::Connecting {
2360 mut info,
2361 next_action,
2362 } = self.inner.state
2363 else {
2364 panic!("Invalid state for completing InitiateContact.");
2365 };
2366
2367 const LOCAL_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
2371 .with_client_id(true)
2372 .with_confidential_channels(true)
2373 .with_gpa_pinning(true);
2374
2375 let (relay_feature_flags, server_specified_monitor_page) = match response {
2376 ModifyConnectionResponse::Supported(
2378 protocol::ConnectionState::SUCCESSFUL,
2379 feature_flags,
2380 server_specified_monitor_page,
2381 ) => (feature_flags, server_specified_monitor_page),
2382 ModifyConnectionResponse::Supported(
2385 connection_state,
2386 feature_flags,
2387 server_specified_monitor_page,
2388 ) => {
2389 tracelimit::error_ratelimited!(
2390 ?connection_state,
2391 "initiate contact failed because relay request failed"
2392 );
2393
2394 info.version.feature_flags &= (feature_flags | LOCAL_FEATURE_FLAGS)
2397 .with_server_specified_monitor_pages(server_specified_monitor_page.is_some());
2398
2399 self.send_version_response(Some(VersionResponseData::new(
2400 info.version,
2401 connection_state,
2402 )));
2403 self.inner.state = ConnectionState::Disconnected;
2404 return;
2405 }
2406 ModifyConnectionResponse::Unsupported => {
2409 self.send_version_response(None);
2410 self.inner.state = ConnectionState::Disconnected;
2411 return;
2412 }
2413 ModifyConnectionResponse::Modified(_) => {
2414 panic!("Invalid response for completing InitiateContact.");
2415 }
2416 };
2417
2418 assert!(
2420 info.version.feature_flags.server_specified_monitor_pages()
2421 || server_specified_monitor_page.is_none()
2422 );
2423
2424 info.version.feature_flags &= relay_feature_flags | LOCAL_FEATURE_FLAGS;
2427
2428 if let Some(gpas) = server_specified_monitor_page {
2432 info.monitor_page = Some(MonitorPageGpaInfo::from_server_gpas(gpas));
2433 info.version
2434 .feature_flags
2435 .set_server_specified_monitor_pages(true);
2436 } else {
2437 info.version
2438 .feature_flags
2439 .set_server_specified_monitor_pages(false);
2440 }
2441
2442 tracelimit::info_ratelimited!(
2443 vtl = self.inner.assigned_channels.vtl as u8,
2444 version = ?info.version,
2445 client_id = ?info.client_id,
2446 trusted = info.trusted,
2447 "guest negotiated version"
2448 );
2449
2450 let version = info.version;
2451 self.inner.state = ConnectionState::Connected(info);
2452
2453 self.send_version_response(Some(
2454 VersionResponseData::new(version, protocol::ConnectionState::SUCCESSFUL)
2455 .with_monitor_pages(server_specified_monitor_page),
2456 ));
2457 if !matches!(next_action, ConnectionAction::None) && self.request_disconnect(next_action) {
2458 self.do_next_action(next_action);
2459 }
2460 }
2461
2462 fn check_version_supported(&self, request: &InitiateContactRequest) -> Option<VersionInfo> {
2464 let version = SUPPORTED_VERSIONS
2465 .iter()
2466 .find(|v| request.version_requested == **v as u32)
2467 .copied()?;
2468
2469 if let Some(max_version) = self.inner.max_version {
2471 if version as u32 > max_version.version {
2472 return None;
2473 }
2474 }
2475
2476 let supported_flags = if version >= Version::Copper {
2477 let max_supported_flags = SUPPORTED_FEATURE_FLAGS
2479 .with_confidential_channels(request.trusted)
2480 .with_gpa_pinning(self.inner.support_gpa_pinning);
2481
2482 if let Some(max_version) = self.inner.max_version {
2484 max_supported_flags & max_version.feature_flags
2485 } else {
2486 max_supported_flags
2487 }
2488 } else {
2489 FeatureFlags::new()
2490 };
2491
2492 let feature_flags = supported_flags & request.feature_flags.into();
2493
2494 assert!(version >= Version::Copper || feature_flags == FeatureFlags::new());
2495 if feature_flags.into_bits() != request.feature_flags {
2496 tracelimit::info_ratelimited!(
2499 supported = feature_flags.into_bits(),
2500 requested = request.feature_flags,
2501 "guest requested unsupported feature flags."
2502 );
2503 }
2504
2505 Some(VersionInfo {
2506 version,
2507 feature_flags,
2508 })
2509 }
2510
2511 fn send_version_response(&mut self, data: Option<VersionResponseData>) {
2512 self.send_version_response_with_target(data, MessageTarget::Default);
2513 }
2514
2515 fn send_version_response_with_target(
2516 &mut self,
2517 data: Option<VersionResponseData>,
2518 target: MessageTarget,
2519 ) {
2520 enum VersionResponseType {
2521 PreCopper,
2522 Copper,
2523 CopperWithServerMnf,
2524 }
2525
2526 let mut response_copper_with_mnf = protocol::VersionResponse3::new_zeroed();
2527 let response_copper = &mut response_copper_with_mnf.version_response2;
2528 let response = &mut response_copper.version_response;
2529 let mut response_type = VersionResponseType::PreCopper;
2530 if let Some(data) = data {
2531 if data.state == protocol::ConnectionState::SUCCESSFUL
2534 || data.version.version >= Version::Win8
2535 {
2536 response.version_supported = 1;
2537 response.connection_state = data.state;
2538 response.selected_version_or_connection_id =
2539 if data.version.version >= Version::Win10Rs3_1 {
2540 self.inner.child_connection_id
2541 } else {
2542 data.version.version as u32
2543 };
2544
2545 if data.version.version >= Version::Copper {
2546 response_copper.supported_features = data.version.feature_flags.into();
2547 response_type = VersionResponseType::Copper;
2548 if let Some(monitor_page) = data.monitor_pages {
2549 assert!(data.version.feature_flags.server_specified_monitor_pages());
2550 response_copper_with_mnf.child_to_parent_monitor_page_gpa =
2551 monitor_page.child_to_parent;
2552 response_copper_with_mnf.parent_to_child_monitor_page_gpa =
2553 monitor_page.parent_to_child;
2554 response_type = VersionResponseType::CopperWithServerMnf;
2555 }
2556 }
2557 }
2558 }
2559
2560 match response_type {
2562 VersionResponseType::PreCopper => {
2563 self.sender().send_message_with_target(response, target)
2564 }
2565 VersionResponseType::Copper => self
2566 .sender()
2567 .send_message_with_target(response_copper, target),
2568 VersionResponseType::CopperWithServerMnf => self
2569 .sender()
2570 .send_message_with_target(&response_copper_with_mnf, target),
2571 }
2572 }
2573
2574 fn request_disconnect(&mut self, new_action: ConnectionAction) -> bool {
2577 assert!(!self.is_resetting());
2578
2579 let gpadls = &mut self.inner.gpadls;
2581 let vm_reset = matches!(new_action, ConnectionAction::Reset);
2582 self.inner.channels.retain(|offer_id, channel| {
2583 (!vm_reset && channel.state.is_reserved())
2585 || !Self::client_release_channel(
2586 self.inner
2587 .pending_messages
2588 .sender(self.notifier, self.inner.state.is_paused()),
2589 offer_id,
2590 channel,
2591 gpadls,
2592 &mut self.inner.incomplete_gpadls,
2593 &mut self.inner.assigned_channels,
2594 &mut self.inner.assigned_monitors,
2595 None,
2596 vm_reset,
2597 )
2598 });
2599
2600 match &mut self.inner.state {
2604 ConnectionState::Disconnected => {
2605 if vm_reset {
2607 if !self.are_channels_reset(true) {
2608 self.inner.state = ConnectionState::Disconnecting {
2609 next_action: ConnectionAction::Reset,
2610 modify_sent: false,
2611 };
2612 }
2613 } else {
2614 assert!(self.are_channels_reset(false));
2615 }
2616 }
2617
2618 ConnectionState::Connected { .. } => {
2619 if self.are_channels_reset(vm_reset) {
2620 self.notify_disconnect(new_action);
2621 } else {
2622 self.inner.state = ConnectionState::Disconnecting {
2623 next_action: new_action,
2624 modify_sent: false,
2625 };
2626 }
2627 }
2628
2629 ConnectionState::Connecting { next_action, .. }
2630 | ConnectionState::Disconnecting { next_action, .. } => {
2631 *next_action = new_action;
2632 }
2633 }
2634
2635 matches!(self.inner.state, ConnectionState::Disconnected)
2636 }
2637
2638 pub(crate) fn complete_disconnect(&mut self) {
2639 if let ConnectionState::Disconnecting {
2640 next_action,
2641 modify_sent,
2642 } = std::mem::replace(&mut self.inner.state, ConnectionState::Disconnected)
2643 {
2644 assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2645 if !modify_sent {
2646 tracelimit::warn_ratelimited!("unexpected modify response");
2647 }
2648
2649 self.inner.state = ConnectionState::Disconnected;
2650 self.do_next_action(next_action);
2651 } else {
2652 unreachable!("not ready for disconnect");
2653 }
2654 }
2655
2656 fn do_next_action(&mut self, action: ConnectionAction) {
2657 match action {
2658 ConnectionAction::None => {}
2659 ConnectionAction::Reset => {
2660 self.complete_reset();
2661 }
2662 ConnectionAction::SendUnloadComplete => {
2663 self.complete_unload();
2664 }
2665 ConnectionAction::Reconnect { initiate_contact } => {
2666 self.initiate_contact(initiate_contact);
2667 }
2668 ConnectionAction::SendFailedVersionResponse => {
2669 self.send_version_response(None);
2672 }
2673 }
2674 }
2675
2676 fn handle_unload(&mut self) {
2678 tracing::debug!(
2679 vtl = self.inner.assigned_channels.vtl as u8,
2680 state = ?self.inner.state,
2681 "VmBus received unload request from guest",
2682 );
2683
2684 if self.request_disconnect(ConnectionAction::SendUnloadComplete) {
2685 self.complete_unload();
2686 }
2687 }
2688
2689 fn complete_unload(&mut self) {
2690 self.notifier.unload_complete();
2691 if let Some(version) = self.inner.delayed_max_version.take() {
2692 self.inner.set_compatibility_version(version, false);
2693 }
2694
2695 self.sender().send_message(&protocol::UnloadComplete {});
2696 tracelimit::info_ratelimited!("Vmbus disconnected");
2697 }
2698
2699 fn handle_request_offers(&mut self) -> Result<(), ChannelError> {
2701 let ConnectionState::Connected(info) = &mut self.inner.state else {
2702 unreachable!(
2703 "in unexpected state {:?}, should be prevented by Message::parse()",
2704 self.inner.state
2705 );
2706 };
2707
2708 if info.offers_sent {
2709 return Err(ChannelError::OffersAlreadySent);
2710 }
2711
2712 info.offers_sent = true;
2713
2714 let mut sorted_channels: Vec<_> = self
2717 .inner
2718 .channels
2719 .iter_mut()
2720 .filter(|(_, channel)| !channel.state.is_reserved())
2721 .collect();
2722
2723 if self.inner.use_absolute_channel_order {
2724 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2725 (
2726 channel.offer.offer_order.unwrap_or(u64::MAX),
2727 channel.offer.interface_id,
2728 channel.offer.instance_id,
2729 )
2730 });
2731 } else {
2732 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2733 (
2734 channel.offer.interface_id,
2735 channel.offer.offer_order.unwrap_or(u64::MAX),
2736 channel.offer.instance_id,
2737 )
2738 });
2739 }
2740
2741 for (offer_id, channel) in sorted_channels {
2742 assert!(matches!(channel.state, ChannelState::ClientReleased));
2743
2744 channel.prepare_channel(
2745 offer_id,
2746 &mut self.inner.assigned_channels,
2747 &mut self.inner.assigned_monitors,
2748 );
2749
2750 channel.state = ChannelState::Closed;
2751 self.inner
2752 .pending_messages
2753 .sender(self.notifier, info.paused)
2754 .send_offer(channel, info);
2755 }
2756 self.sender().send_message(&protocol::AllOffersDelivered {});
2757
2758 Ok(())
2759 }
2760
2761 fn gpadl_completed(
2763 mut sender: MessageSender<'_, N>,
2764 offer_id: OfferId,
2765 channel: &Channel,
2766 gpadl_id: GpadlId,
2767 gpadl: &mut Gpadl,
2768 ) {
2769 if channel.state.is_revoked() {
2770 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2771
2772 gpadl.state = GpadlState::Accepted;
2776 sender.send_gpadl_created(channel_id, gpadl_id, protocol::STATUS_SUCCESS);
2777 } else {
2778 sender.notifier.notify(
2780 offer_id,
2781 Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
2782 );
2783 }
2784 }
2785
2786 fn handle_gpadl_header_core(
2788 &mut self,
2789 input: &protocol::GpadlHeader,
2790 range: &[u8],
2791 ) -> Result<(), ChannelError> {
2792 let (offer_id, channel) = self
2794 .inner
2795 .channels
2796 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2797
2798 if channel.state.is_reserved() {
2801 return Err(ChannelError::ChannelReserved);
2802 }
2803
2804 let mut gpadl = Gpadl::new(input.count, input.len as usize / 8);
2806 let done = gpadl.append(range)?;
2807
2808 let gpadl = match self.inner.gpadls.entry((input.gpadl_id, offer_id)) {
2810 Entry::Vacant(entry) => entry.insert(gpadl),
2811 Entry::Occupied(_) => return Err(ChannelError::DuplicateGpadlId),
2812 };
2813
2814 if done {
2815 Self::gpadl_completed(
2816 self.inner
2817 .pending_messages
2818 .sender(self.notifier, self.inner.state.is_paused()),
2819 offer_id,
2820 channel,
2821 input.gpadl_id,
2822 gpadl,
2823 )
2824 } else {
2825 match self.inner.incomplete_gpadls.entry(input.gpadl_id) {
2831 Entry::Vacant(entry) => {
2832 entry.insert(offer_id);
2833 }
2834 Entry::Occupied(_) => {
2835 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2836 tracelimit::error_ratelimited!(
2837 channel_id = ?input.channel_id,
2838 key = %channel.offer.key(),
2839 gpadl_id = ?input.gpadl_id,
2840 "duplicate in-progress gpadl ID",
2841 );
2842 return Err(ChannelError::DuplicateGpadlId);
2843 }
2844 }
2845 }
2846 Ok(())
2847 }
2848
2849 fn handle_gpadl_header(&mut self, input: &protocol::GpadlHeader, range: &[u8]) {
2851 if let Err(err) = self.handle_gpadl_header_core(input, range) {
2852 tracelimit::warn_ratelimited!(
2853 err = &err as &dyn std::error::Error,
2854 channel_id = ?input.channel_id,
2855 key = %self.inner.channels.get_by_channel_id(&self.inner.assigned_channels, input.channel_id).map(|(_, c)| c.offer.key()).unwrap_or_default(),
2856 gpadl_id = ?input.gpadl_id,
2857 "error handling gpadl header"
2858 );
2859
2860 self.sender().send_gpadl_created(
2862 input.channel_id,
2863 input.gpadl_id,
2864 protocol::STATUS_UNSUCCESSFUL,
2865 );
2866 }
2867 }
2868
2869 fn handle_gpadl_body(
2875 &mut self,
2876 input: &protocol::GpadlBody,
2877 range: &[u8],
2878 ) -> Result<(), ChannelError> {
2879 let &offer_id = self
2883 .inner
2884 .incomplete_gpadls
2885 .get(&input.gpadl_id)
2886 .ok_or(ChannelError::UnknownGpadlId)?;
2887 let gpadl = self
2888 .inner
2889 .gpadls
2890 .get_mut(&(input.gpadl_id, offer_id))
2891 .ok_or(ChannelError::UnknownGpadlId)?;
2892 let channel = &mut self.inner.channels[offer_id];
2893
2894 match gpadl.append(range) {
2895 Ok(done) => {
2896 if done {
2897 self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2898 Self::gpadl_completed(
2899 self.inner
2900 .pending_messages
2901 .sender(self.notifier, self.inner.state.is_paused()),
2902 offer_id,
2903 channel,
2904 input.gpadl_id,
2905 gpadl,
2906 )
2907 }
2908 }
2909 Err(err) => {
2910 self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2911 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2912 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2913 tracelimit::warn_ratelimited!(
2914 err = &err as &dyn std::error::Error,
2915 channel_id = channel_id.0,
2916 key = %channel.offer.key(),
2917 gpadl_id = input.gpadl_id.0,
2918 "error handling gpadl body"
2919 );
2920 self.sender().send_gpadl_created(
2921 channel_id,
2922 input.gpadl_id,
2923 protocol::STATUS_UNSUCCESSFUL,
2924 );
2925 }
2926 }
2927
2928 Ok(())
2929 }
2930
2931 fn handle_gpadl_teardown(
2933 &mut self,
2934 input: &protocol::GpadlTeardown,
2935 ) -> Result<(), ChannelError> {
2936 let (offer_id, channel) = self
2937 .inner
2938 .channels
2939 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2940
2941 tracing::debug!(
2942 channel_id = input.channel_id.0,
2943 key = %channel.offer.key(),
2944 gpadl_id = input.gpadl_id.0,
2945 "Received GPADL teardown request"
2946 );
2947
2948 let gpadl = self
2949 .inner
2950 .gpadls
2951 .get_mut(&(input.gpadl_id, offer_id))
2952 .ok_or(ChannelError::UnknownGpadlId)?;
2953
2954 match gpadl.state {
2955 GpadlState::InProgress
2956 | GpadlState::Offered
2957 | GpadlState::OfferedTearingDown
2958 | GpadlState::TearingDown => {
2959 return Err(ChannelError::InvalidGpadlState);
2960 }
2961 GpadlState::Accepted => {
2962 if channel.info.as_ref().map(|info| info.channel_id) != Some(input.channel_id) {
2963 return Err(ChannelError::WrongGpadlChannelId);
2964 }
2965
2966 if channel.state.is_reserved() {
2970 return Err(ChannelError::ChannelReserved);
2971 }
2972
2973 if channel.state.is_revoked() {
2974 tracing::trace!(
2975 channel_id = input.channel_id.0,
2976 key = %channel.offer.key(),
2977 gpadl_id = input.gpadl_id.0,
2978 "Gpadl teardown for revoked channel"
2979 );
2980
2981 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2982 self.sender().send_gpadl_torndown(input.gpadl_id);
2983 } else {
2984 gpadl.state = GpadlState::TearingDown;
2985 self.notifier.notify(
2986 offer_id,
2987 Action::TeardownGpadl {
2988 gpadl_id: input.gpadl_id,
2989 post_restore: false,
2990 },
2991 );
2992 }
2993 }
2994 }
2995 Ok(())
2996 }
2997
2998 fn open_channel(
3001 &mut self,
3002 offer_id: OfferId,
3003 input: &OpenRequest,
3004 reserved_state: Option<ReservedState>,
3005 ) {
3006 let channel = &mut self.inner.channels[offer_id];
3007 assert!(matches!(channel.state, ChannelState::Closed));
3008
3009 channel.state = ChannelState::Opening {
3010 request: *input,
3011 reserved_state,
3012 };
3013
3014 let info = channel.info.as_ref().expect("assigned");
3017 self.notifier.notify(
3018 offer_id,
3019 Action::Open(
3020 OpenParams::from_request(
3021 info,
3022 input,
3023 channel.handled_monitor_info(),
3024 reserved_state.map(|state| state.target),
3025 ),
3026 self.inner.state.get_version().expect("must be connected"),
3027 ),
3028 );
3029 }
3030
3031 fn handle_open_channel(&mut self, input: &protocol::OpenChannel2) -> Result<(), ChannelError> {
3033 let (offer_id, channel) = self
3034 .inner
3035 .channels
3036 .get_by_channel_id_mut(&self.inner.assigned_channels, input.open_channel.channel_id)?;
3037
3038 let guest_specified_interrupt_info = self
3039 .inner
3040 .state
3041 .check_feature_flags(|ff| ff.guest_specified_signal_parameters())
3042 .then_some(SignalInfo {
3043 event_flag: input.event_flag,
3044 connection_id: input.connection_id,
3045 });
3046
3047 let flags = if self
3048 .inner
3049 .state
3050 .check_feature_flags(|ff| ff.channel_interrupt_redirection())
3051 {
3052 input.flags
3053 } else {
3054 Default::default()
3055 };
3056
3057 let request = OpenRequest {
3058 open_id: input.open_channel.open_id,
3059 ring_buffer_gpadl_id: input.open_channel.ring_buffer_gpadl_id,
3060 target_vp: protocol::vp_index_if_enabled(input.open_channel.target_vp),
3061 downstream_ring_buffer_page_offset: input
3062 .open_channel
3063 .downstream_ring_buffer_page_offset,
3064 user_data: input.open_channel.user_data,
3065 guest_specified_interrupt_info,
3066 flags,
3067 };
3068
3069 match channel.state {
3070 ChannelState::Closed => self.open_channel(offer_id, &request, None),
3071 ChannelState::Closing { params, .. } => {
3072 channel.state = ChannelState::ClosingReopen { params, request }
3076 }
3077 ChannelState::Revoked | ChannelState::Reoffered => {}
3078
3079 ChannelState::Open { .. }
3080 | ChannelState::Opening { .. }
3081 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelAlreadyOpen),
3082
3083 ChannelState::ClientReleased
3084 | ChannelState::ClosingClientRelease
3085 | ChannelState::OpeningClientRelease => unreachable!(),
3086 }
3087 Ok(())
3088 }
3089
3090 fn handle_close_channel(&mut self, input: &protocol::CloseChannel) -> Result<(), ChannelError> {
3092 let (offer_id, channel) = self
3093 .inner
3094 .channels
3095 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3096
3097 match channel.state {
3098 ChannelState::Open {
3099 params,
3100 modify_state,
3101 reserved_state: None,
3102 } => {
3103 if modify_state.is_modifying() {
3104 tracelimit::warn_ratelimited!(
3105 key = %channel.offer.key(),
3106 ?modify_state,
3107 "Client is closing the channel with a modify in progress"
3108 )
3109 }
3110
3111 channel.state = ChannelState::Closing {
3112 params,
3113 reserved_state: None,
3114 };
3115 self.notifier.notify(offer_id, Action::Close);
3116 }
3117
3118 ChannelState::Open {
3119 reserved_state: Some(_),
3120 ..
3121 } => return Err(ChannelError::ChannelReserved),
3122
3123 ChannelState::Revoked | ChannelState::Reoffered => {}
3124
3125 ChannelState::Closed
3126 | ChannelState::Opening { .. }
3127 | ChannelState::Closing { .. }
3128 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3129
3130 ChannelState::ClientReleased
3131 | ChannelState::ClosingClientRelease
3132 | ChannelState::OpeningClientRelease => unreachable!(),
3133 }
3134
3135 Ok(())
3136 }
3137
3138 fn handle_open_reserved_channel(
3141 &mut self,
3142 input: &protocol::OpenReservedChannel,
3143 version: VersionInfo,
3144 ) -> Result<(), ChannelError> {
3145 let (offer_id, channel) = self
3146 .inner
3147 .channels
3148 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3149
3150 let target = ConnectionTarget {
3151 vp: input.target_vp,
3152 sint: input.target_sint as u8,
3153 };
3154
3155 let reserved_state = Some(ReservedState { version, target });
3156
3157 let request = OpenRequest {
3158 ring_buffer_gpadl_id: input.ring_buffer_gpadl,
3159 target_vp: None,
3161 downstream_ring_buffer_page_offset: input.downstream_page_offset,
3162 open_id: 0,
3163 user_data: UserDefinedData::new_zeroed(),
3164 guest_specified_interrupt_info: None,
3165 flags: Default::default(),
3166 };
3167
3168 match channel.state {
3169 ChannelState::Closed => self.open_channel(offer_id, &request, reserved_state),
3170 ChannelState::Revoked | ChannelState::Reoffered => {}
3171
3172 ChannelState::Open { .. } | ChannelState::Opening { .. } => {
3173 return Err(ChannelError::ChannelAlreadyOpen);
3174 }
3175
3176 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3177 return Err(ChannelError::InvalidChannelState);
3178 }
3179
3180 ChannelState::ClientReleased
3181 | ChannelState::ClosingClientRelease
3182 | ChannelState::OpeningClientRelease => unreachable!(),
3183 }
3184 Ok(())
3185 }
3186
3187 fn handle_close_reserved_channel(
3190 &mut self,
3191 input: &protocol::CloseReservedChannel,
3192 ) -> Result<(), ChannelError> {
3193 let (offer_id, channel) = self
3194 .inner
3195 .channels
3196 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3197
3198 match channel.state {
3199 ChannelState::Open {
3200 params,
3201 reserved_state: Some(mut resvd),
3202 ..
3203 } => {
3204 resvd.target.vp = input.target_vp;
3205 resvd.target.sint = input.target_sint as u8;
3206 channel.state = ChannelState::Closing {
3207 params,
3208 reserved_state: Some(resvd),
3209 };
3210 self.notifier.notify(offer_id, Action::Close);
3211 }
3212
3213 ChannelState::Open {
3214 reserved_state: None,
3215 ..
3216 } => return Err(ChannelError::ChannelNotReserved),
3217
3218 ChannelState::Revoked | ChannelState::Reoffered => {}
3219
3220 ChannelState::Closed
3221 | ChannelState::Opening { .. }
3222 | ChannelState::Closing { .. }
3223 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3224
3225 ChannelState::ClientReleased
3226 | ChannelState::ClosingClientRelease
3227 | ChannelState::OpeningClientRelease => unreachable!(),
3228 }
3229
3230 Ok(())
3231 }
3232
3233 #[must_use]
3237 fn client_release_channel(
3238 mut sender: MessageSender<'_, N>,
3239 offer_id: OfferId,
3240 channel: &mut Channel,
3241 gpadls: &mut GpadlMap,
3242 incomplete_gpadls: &mut IncompleteGpadlMap,
3243 assigned_channels: &mut AssignedChannels,
3244 assigned_monitors: &mut AssignedMonitors,
3245 info: Option<&ConnectionInfo>,
3246 vm_reset: bool,
3247 ) -> bool {
3248 tracelimit::info_ratelimited!(?offer_id, key = %channel.offer.key(), "client released channel");
3249 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3251 if gpadl_offer_id != offer_id {
3252 return true;
3253 }
3254 match gpadl.state {
3255 GpadlState::InProgress => {
3256 incomplete_gpadls.remove(&gpadl_id);
3257 false
3258 }
3259 GpadlState::Offered => {
3260 gpadl.state = GpadlState::OfferedTearingDown;
3261 true
3262 }
3263 GpadlState::Accepted => {
3264 if channel.state.is_revoked() {
3265 false
3267 } else {
3268 gpadl.state = GpadlState::TearingDown;
3269 sender.notifier.notify(
3270 offer_id,
3271 Action::TeardownGpadl {
3272 gpadl_id,
3273 post_restore: false,
3274 },
3275 );
3276 true
3277 }
3278 }
3279 GpadlState::OfferedTearingDown | GpadlState::TearingDown => true,
3280 }
3281 });
3282
3283 let remove = match &mut channel.state {
3284 ChannelState::Closed => {
3285 channel.state = ChannelState::ClientReleased;
3286 false
3287 }
3288 ChannelState::Reoffered => {
3289 if let Some(info) = info {
3290 channel.state = ChannelState::Closed;
3291 channel.restore_state = RestoreState::New;
3292 sender.send_offer(channel, info);
3293 return false;
3295 }
3296 channel.state = ChannelState::ClientReleased;
3297 false
3298 }
3299 ChannelState::Revoked => {
3300 channel.state = ChannelState::ClientReleased;
3301 true
3302 }
3303 ChannelState::Opening { .. } => {
3304 if vm_reset {
3322 channel.state = ChannelState::ClientReleased;
3323 } else {
3324 channel.state = ChannelState::OpeningClientRelease;
3325 }
3326 false
3327 }
3328 ChannelState::Open { .. } => {
3329 channel.state = ChannelState::ClosingClientRelease;
3330 sender.notifier.notify(offer_id, Action::Close);
3331 false
3332 }
3333 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3334 channel.state = ChannelState::ClosingClientRelease;
3335 false
3336 }
3337
3338 ChannelState::ClosingClientRelease
3339 | ChannelState::OpeningClientRelease
3340 | ChannelState::ClientReleased => false,
3341 };
3342
3343 assert!(channel.state.is_released());
3344
3345 channel.release_channel(offer_id, assigned_channels, assigned_monitors);
3346 remove
3347 }
3348
3349 fn handle_rel_id_released(
3351 &mut self,
3352 input: &protocol::RelIdReleased,
3353 ) -> Result<(), ChannelError> {
3354 let channel_id = input.channel_id;
3355 let (offer_id, channel) = self
3356 .inner
3357 .channels
3358 .get_by_channel_id_mut(&self.inner.assigned_channels, channel_id)?;
3359
3360 match channel.state {
3361 ChannelState::Closed
3362 | ChannelState::Revoked
3363 | ChannelState::Closing { .. }
3364 | ChannelState::Reoffered => {
3365 if Self::client_release_channel(
3366 self.inner
3367 .pending_messages
3368 .sender(self.notifier, self.inner.state.is_paused()),
3369 offer_id,
3370 channel,
3371 &mut self.inner.gpadls,
3372 &mut self.inner.incomplete_gpadls,
3373 &mut self.inner.assigned_channels,
3374 &mut self.inner.assigned_monitors,
3375 self.inner.state.get_connected_info(),
3376 false,
3377 ) {
3378 self.inner.channels.remove(offer_id);
3379 }
3380
3381 self.check_disconnected();
3382 }
3383
3384 ChannelState::Opening { .. }
3385 | ChannelState::Open { .. }
3386 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::InvalidChannelState),
3387
3388 ChannelState::ClientReleased
3389 | ChannelState::OpeningClientRelease
3390 | ChannelState::ClosingClientRelease => unreachable!(),
3391 }
3392 Ok(())
3393 }
3394
3395 fn handle_tl_connect_request(&mut self, request: protocol::TlConnectRequest2) {
3398 let version = self
3399 .inner
3400 .state
3401 .get_version()
3402 .expect("must be connected")
3403 .version;
3404
3405 let hosted_silo_unaware = version < Version::Win10Rs5;
3406 self.notifier
3407 .notify_hvsock(&HvsockConnectRequest::from_message(
3408 request,
3409 hosted_silo_unaware,
3410 ));
3411 }
3412
3413 pub fn send_tl_connect_result(&mut self, result: HvsockConnectResult) {
3415 if !result.success && self.inner.state.check_version(Version::Win10Rs3_0) {
3419 self.sender().send_message(&protocol::TlConnectResult {
3423 service_id: result.service_id,
3424 endpoint_id: result.endpoint_id,
3425 status: protocol::STATUS_CONNECTION_REFUSED,
3426 })
3427 }
3428 }
3429
3430 fn handle_modify_channel(
3433 &mut self,
3434 request: &protocol::ModifyChannel,
3435 ) -> Result<(), ChannelError> {
3436 let result = self.modify_channel(request);
3437 if result.is_err() {
3438 self.send_modify_channel_response(request.channel_id, protocol::STATUS_UNSUCCESSFUL);
3439 }
3440
3441 result
3442 }
3443
3444 fn modify_channel(&mut self, request: &protocol::ModifyChannel) -> Result<(), ChannelError> {
3446 if request.target_vp == protocol::VP_INDEX_DISABLE_INTERRUPT {
3448 return Err(ChannelError::InvalidTargetVp);
3449 }
3450
3451 let (offer_id, channel) = self
3452 .inner
3453 .channels
3454 .get_by_channel_id_mut(&self.inner.assigned_channels, request.channel_id)?;
3455
3456 let (open_request, modify_state) = match &mut channel.state {
3457 ChannelState::Open {
3458 params,
3459 modify_state,
3460 reserved_state: None,
3461 } => (params, modify_state),
3462 _ => return Err(ChannelError::InvalidChannelState),
3463 };
3464
3465 if open_request.target_vp.is_none() {
3466 return Err(ChannelError::InterruptsDisabled);
3467 }
3468
3469 if let ModifyState::Modifying { pending_target_vp } = modify_state {
3470 if self.inner.state.check_version(Version::Iron) {
3471 tracelimit::warn_ratelimited!(
3474 key = %channel.offer.key(),
3475 "Client sent new ModifyChannel before receiving ModifyChannelResponse."
3476 );
3477 } else {
3478 *pending_target_vp = Some(request.target_vp);
3481 }
3482 } else {
3483 self.notifier.notify(
3484 offer_id,
3485 Action::Modify {
3486 target_vp: request.target_vp,
3487 },
3488 );
3489
3490 open_request.target_vp = Some(request.target_vp);
3492 *modify_state = ModifyState::Modifying {
3493 pending_target_vp: None,
3494 };
3495 }
3496
3497 Ok(())
3498 }
3499
3500 pub fn modify_channel_complete(&mut self, offer_id: OfferId, status: i32) {
3507 let channel = &mut self.inner.channels[offer_id];
3508
3509 if let ChannelState::Open {
3510 params,
3511 modify_state: ModifyState::Modifying { pending_target_vp },
3512 reserved_state: None,
3513 } = channel.state
3514 {
3515 channel.state = ChannelState::Open {
3516 params,
3517 modify_state: ModifyState::NotModifying,
3518 reserved_state: None,
3519 };
3520
3521 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
3523 let key = channel.offer.key();
3524 self.send_modify_channel_response(channel_id, status);
3525
3526 if let Some(target_vp) = pending_target_vp {
3528 let request = protocol::ModifyChannel {
3529 channel_id,
3530 target_vp,
3531 };
3532
3533 if let Err(error) = self.handle_modify_channel(&request) {
3534 tracelimit::warn_ratelimited!(?error, %key, "Pending ModifyChannel request failed.")
3535 }
3536 }
3537 }
3538 }
3539
3540 fn send_modify_channel_response(&mut self, channel_id: ChannelId, status: i32) {
3541 if self.inner.state.check_version(Version::Iron) {
3542 self.sender()
3543 .send_message(&protocol::ModifyChannelResponse { channel_id, status });
3544 }
3545 }
3546
3547 fn handle_modify_connection(&mut self, request: protocol::ModifyConnection) {
3548 if let Err(err) = self.modify_connection(request) {
3549 tracelimit::error_ratelimited!(?err, "modifying connection failed");
3550 self.complete_modify_connection(ModifyConnectionResponse::Modified(
3551 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
3552 ));
3553 }
3554 }
3555
3556 fn modify_connection(&mut self, request: protocol::ModifyConnection) -> anyhow::Result<()> {
3557 let ConnectionState::Connected(info) = &mut self.inner.state else {
3558 anyhow::bail!(
3559 "Invalid state for ModifyConnection request: {:?}",
3560 self.inner.state
3561 );
3562 };
3563
3564 if info.modifying {
3565 anyhow::bail!(
3566 "Duplicate ModifyConnection request, state: {:?}",
3567 self.inner.state
3568 );
3569 }
3570
3571 if matches!(
3572 info.monitor_page,
3573 Some(MonitorPageGpaInfo {
3574 server_allocated: true,
3575 ..
3576 })
3577 ) {
3578 anyhow::bail!("Cannot modify server-allocated monitor pages");
3579 }
3580
3581 if (request.child_to_parent_monitor_page_gpa == 0)
3582 != (request.parent_to_child_monitor_page_gpa == 0)
3583 {
3584 anyhow::bail!("Guest must specify either both or no monitor pages, {request:?}");
3585 }
3586
3587 let monitor_page = (request.child_to_parent_monitor_page_gpa != 0).then_some(
3588 MonitorPageGpaInfo::from_guest_gpas(MonitorPageGpas {
3589 child_to_parent: request.child_to_parent_monitor_page_gpa,
3590 parent_to_child: request.parent_to_child_monitor_page_gpa,
3591 }),
3592 );
3593
3594 info.modifying = true;
3595 info.monitor_page = monitor_page;
3596 tracing::debug!("modifying connection parameters.");
3597 self.notifier.modify_connection(request.into())?;
3598
3599 Ok(())
3600 }
3601
3602 pub fn complete_modify_connection(&mut self, response: ModifyConnectionResponse) {
3603 tracing::debug!(?response, "modifying connection parameters complete");
3604
3605 match &mut self.inner.state {
3609 ConnectionState::Connecting { .. } => self.complete_initiate_contact(response),
3610 ConnectionState::Disconnecting { .. } => self.complete_disconnect(),
3611 ConnectionState::Connected(info) => {
3612 let ModifyConnectionResponse::Modified(connection_state) = response else {
3613 panic!(
3614 "Relay should not return {:?} for a modify request with no version.",
3615 response
3616 );
3617 };
3618
3619 if !info.modifying {
3620 panic!(
3621 "ModifyConnection response while not modifying, state: {:?}",
3622 self.inner.state
3623 );
3624 }
3625
3626 info.modifying = false;
3627 self.sender()
3628 .send_message(&protocol::ModifyConnectionResponse { connection_state });
3629 }
3630 _ => panic!(
3631 "Invalid state for ModifyConnection response: {:?}",
3632 self.inner.state
3633 ),
3634 }
3635 }
3636
3637 fn handle_pause(&mut self) {
3638 tracelimit::info_ratelimited!("pausing sending messages");
3639 self.sender().send_message(&protocol::PauseResponse {});
3640 let ConnectionState::Connected(info) = &mut self.inner.state else {
3641 unreachable!(
3642 "in unexpected state {:?}, should be prevented by Message::parse()",
3643 self.inner.state
3644 );
3645 };
3646 info.paused = true;
3647 }
3648
3649 pub fn handle_synic_message(&mut self, message: SynicMessage) -> Result<(), ChannelError> {
3651 assert!(!self.is_resetting());
3652
3653 let version = self.inner.state.get_version();
3654 let msg = Message::parse(&message.data, version)?;
3655 tracing::trace!(?msg, message.trusted, "received vmbus message");
3656 if self.inner.state.is_trusted() && !message.trusted {
3661 tracelimit::warn_ratelimited!(?msg, "Received untrusted message");
3662 return Err(ChannelError::UntrustedMessage);
3663 }
3664
3665 match &mut self.inner.state {
3667 ConnectionState::Connected(info) if info.paused => {
3668 if !matches!(
3669 msg,
3670 Message::Resume(..)
3671 | Message::Unload(..)
3672 | Message::InitiateContact { .. }
3673 | Message::InitiateContact2 { .. }
3674 ) {
3675 tracelimit::warn_ratelimited!(?msg, "Received message while paused");
3676 return Err(ChannelError::Paused);
3677 }
3678 tracelimit::info_ratelimited!("resuming sending messages");
3679 info.paused = false;
3680 }
3681 _ => {}
3682 }
3683
3684 match msg {
3685 Message::InitiateContact2(input, ..) => {
3686 self.handle_initiate_contact(&input, &message, true)?
3687 }
3688 Message::InitiateContact(input, ..) => {
3689 self.handle_initiate_contact(&input.into(), &message, false)?
3690 }
3691 Message::Unload(..) => self.handle_unload(),
3692 Message::RequestOffers(..) => self.handle_request_offers()?,
3693 Message::GpadlHeader(input, range) => self.handle_gpadl_header(&input, range),
3694 Message::GpadlBody(input, range) => self.handle_gpadl_body(&input, range)?,
3695 Message::GpadlTeardown(input, ..) => self.handle_gpadl_teardown(&input)?,
3696 Message::OpenChannel(input, ..) => self.handle_open_channel(&input.into())?,
3697 Message::OpenChannel2(input, ..) => self.handle_open_channel(&input)?,
3698 Message::CloseChannel(input, ..) => self.handle_close_channel(&input)?,
3699 Message::RelIdReleased(input, ..) => self.handle_rel_id_released(&input)?,
3700 Message::TlConnectRequest(input, ..) => self.handle_tl_connect_request(input.into()),
3701 Message::TlConnectRequest2(input, ..) => self.handle_tl_connect_request(input),
3702 Message::ModifyChannel(input, ..) => self.handle_modify_channel(&input)?,
3703 Message::ModifyConnection(input, ..) => self.handle_modify_connection(input),
3704 Message::OpenReservedChannel(input, ..) => self.handle_open_reserved_channel(
3705 &input,
3706 version.expect("version validated by Message::parse"),
3707 )?,
3708 Message::CloseReservedChannel(input, ..) => {
3709 self.handle_close_reserved_channel(&input)?
3710 }
3711 Message::Pause(protocol::Pause, ..) => self.handle_pause(),
3712 Message::Resume(protocol::Resume, ..) => {}
3713 Message::OfferChannel(..)
3715 | Message::RescindChannelOffer(..)
3716 | Message::AllOffersDelivered(..)
3717 | Message::OpenResult(..)
3718 | Message::GpadlCreated(..)
3719 | Message::GpadlTorndown(..)
3720 | Message::VersionResponse(..)
3721 | Message::VersionResponse2(..)
3722 | Message::VersionResponse3(..)
3723 | Message::UnloadComplete(..)
3724 | Message::CloseReservedChannelResponse(..)
3725 | Message::TlConnectResult(..)
3726 | Message::ModifyChannelResponse(..)
3727 | Message::ModifyConnectionResponse(..)
3728 | Message::PauseResponse(..) => {
3729 unreachable!("Server received client message {:?}", msg);
3730 }
3731 }
3732 Ok(())
3733 }
3734
3735 pub fn gpadl_create_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId, status: i32) {
3737 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3738 tracelimit::error_ratelimited!(
3739 ?offer_id,
3740 key = %self.inner.channels[offer_id].offer.key(),
3741 ?gpadl_id,
3742 "invalid gpadl ID for channel"
3743 );
3744 return;
3745 };
3746 let retain = match gpadl.state {
3747 GpadlState::InProgress | GpadlState::TearingDown | GpadlState::Accepted => {
3748 tracelimit::error_ratelimited!(?offer_id, ?gpadl_id, ?gpadl, "invalid gpadl state");
3749 return;
3750 }
3751 GpadlState::Offered => {
3752 let channel_id = self.inner.channels[offer_id]
3753 .info
3754 .as_ref()
3755 .expect("assigned")
3756 .channel_id;
3757 self.inner
3758 .pending_messages
3759 .sender(self.notifier, self.inner.state.is_paused())
3760 .send_gpadl_created(channel_id, gpadl_id, status);
3761 if status >= 0 {
3762 gpadl.state = GpadlState::Accepted;
3763 true
3764 } else {
3765 false
3766 }
3767 }
3768 GpadlState::OfferedTearingDown => {
3769 if status >= 0 {
3770 self.notifier.notify(
3772 offer_id,
3773 Action::TeardownGpadl {
3774 gpadl_id,
3775 post_restore: false,
3776 },
3777 );
3778 gpadl.state = GpadlState::TearingDown;
3779 true
3780 } else {
3781 false
3782 }
3783 }
3784 };
3785 if !retain {
3786 self.inner
3787 .gpadls
3788 .remove(&(gpadl_id, offer_id))
3789 .expect("gpadl validated above");
3790
3791 self.check_disconnected();
3792 }
3793 }
3794
3795 pub fn gpadl_teardown_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId) {
3797 let channel = &mut self.inner.channels[offer_id];
3798 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3799 tracelimit::error_ratelimited!(
3800 ?offer_id,
3801 key = %channel.offer.key(),
3802 ?gpadl_id,
3803 "invalid gpadl ID for channel"
3804 );
3805 return;
3806 };
3807 tracing::debug!(
3808 offer_id = offer_id.0,
3809 key = %channel.offer.key(),
3810 gpadl_id = gpadl_id.0,
3811 "Gpadl teardown complete"
3812 );
3813 match gpadl.state {
3814 GpadlState::InProgress
3815 | GpadlState::Offered
3816 | GpadlState::OfferedTearingDown
3817 | GpadlState::Accepted => {
3818 tracelimit::error_ratelimited!(?offer_id, key = %channel.offer.key(), ?gpadl_id, ?gpadl, "invalid gpadl state");
3819 }
3820 GpadlState::TearingDown => {
3821 if !channel.state.is_released() {
3822 self.sender().send_gpadl_torndown(gpadl_id);
3823 }
3824 self.inner
3825 .gpadls
3826 .remove(&(gpadl_id, offer_id))
3827 .expect("gpadl validated above");
3828
3829 self.check_disconnected();
3830 }
3831 }
3832 }
3833
3834 fn sender(&mut self) -> MessageSender<'_, N> {
3839 self.inner
3840 .pending_messages
3841 .sender(self.notifier, self.inner.state.is_paused())
3842 }
3843}
3844
3845fn revoke<N: Notifier>(
3846 mut sender: MessageSender<'_, N>,
3847 offer_id: OfferId,
3848 channel: &mut Channel,
3849 gpadls: &mut GpadlMap,
3850) -> bool {
3851 let info = match channel.state {
3852 ChannelState::Closed
3853 | ChannelState::Open { .. }
3854 | ChannelState::Opening { .. }
3855 | ChannelState::Closing { .. }
3856 | ChannelState::ClosingReopen { .. } => {
3857 channel.state = ChannelState::Revoked;
3858 Some(channel.info.as_ref().expect("assigned"))
3859 }
3860 ChannelState::Reoffered => {
3861 channel.state = ChannelState::Revoked;
3862 None
3863 }
3864 ChannelState::ClientReleased
3865 | ChannelState::OpeningClientRelease
3866 | ChannelState::ClosingClientRelease => None,
3867 ChannelState::Revoked => return true,
3869 };
3870 let retain = !channel.state.is_released();
3871
3872 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3874 if gpadl_offer_id != offer_id {
3875 return true;
3876 }
3877
3878 match gpadl.state {
3879 GpadlState::InProgress => true,
3880 GpadlState::Offered => {
3881 if let Some(info) = info {
3882 sender.send_gpadl_created(
3883 info.channel_id,
3884 gpadl_id,
3885 protocol::STATUS_UNSUCCESSFUL,
3886 );
3887 }
3888 false
3889 }
3890 GpadlState::OfferedTearingDown => false,
3891 GpadlState::Accepted => true,
3892 GpadlState::TearingDown => {
3893 if info.is_some() {
3894 sender.send_gpadl_torndown(gpadl_id);
3895 }
3896 false
3897 }
3898 }
3899 });
3900 if let Some(info) = info {
3901 sender.send_rescind(info);
3902 }
3903 if channel.restore_state != RestoreState::New {
3905 channel.restore_state = RestoreState::Restored;
3906 }
3907 retain
3908}
3909
3910struct PendingMessages(VecDeque<OutgoingMessage>);
3911
3912impl PendingMessages {
3913 fn sender<'a, N: Notifier>(
3915 &'a mut self,
3916 notifier: &'a mut N,
3917 is_paused: bool,
3918 ) -> MessageSender<'a, N> {
3919 MessageSender {
3920 notifier,
3921 pending_messages: self,
3922 is_paused,
3923 }
3924 }
3925}
3926
3927struct MessageSender<'a, N> {
3930 notifier: &'a mut N,
3931 pending_messages: &'a mut PendingMessages,
3932 is_paused: bool,
3933}
3934
3935impl<N: Notifier> MessageSender<'_, N> {
3936 fn send_message<
3938 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3939 >(
3940 &mut self,
3941 msg: &T,
3942 ) {
3943 let message = OutgoingMessage::new(msg);
3944
3945 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3946 if !self.pending_messages.0.is_empty()
3948 || self.is_paused
3949 || !self.notifier.send_message(&message, MessageTarget::Default)
3950 {
3951 tracing::trace!("message queued");
3952 self.pending_messages.0.push_back(message);
3954 }
3955 }
3956
3957 fn send_message_with_target<
3959 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3960 >(
3961 &mut self,
3962 msg: &T,
3963 target: MessageTarget,
3964 ) {
3965 if target == MessageTarget::Default {
3966 self.send_message(msg);
3967 } else {
3968 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3969 let message = OutgoingMessage::new(msg);
3972 if !self.notifier.send_message(&message, target) {
3973 tracelimit::warn_ratelimited!(?target, "failed to send message");
3974 }
3975 }
3976 }
3977
3978 fn send_offer(&mut self, channel: &mut Channel, connection_info: &ConnectionInfo) {
3980 let info = channel.info.as_ref().expect("assigned");
3981 let mut flags = channel.offer.flags;
3982
3983 if !connection_info
3985 .version
3986 .feature_flags
3987 .confidential_channels()
3988 {
3989 flags.set_confidential_ring_buffer(false);
3990 flags.set_confidential_external_memory(false);
3991 }
3992
3993 if !connection_info.version.feature_flags.gpa_pinning() {
3994 flags.set_require_pinned_external_memory(false);
3995 }
3996
3997 let monitor_id = connection_info.monitor_page.and(info.monitor_id);
4004 let msg = protocol::OfferChannel {
4005 interface_id: channel.offer.interface_id,
4006 instance_id: channel.offer.instance_id,
4007 rsvd: [0; 4],
4008 flags,
4009 mmio_megabytes: channel.offer.mmio_megabytes,
4010 user_defined: channel.offer.user_defined,
4011 subchannel_index: channel.offer.subchannel_index,
4012 mmio_megabytes_optional: channel.offer.mmio_megabytes_optional,
4013 channel_id: info.channel_id,
4014 monitor_id: monitor_id.unwrap_or(MonitorId::INVALID).0,
4015 monitor_allocated: monitor_id.is_some().into(),
4016 is_dedicated: 1,
4019 connection_id: info.connection_id,
4020 };
4021 tracing::info!(
4022 channel_id = msg.channel_id.0,
4023 connection_id = msg.connection_id,
4024 key = %channel.offer.key(),
4025 "sending offer to guest"
4026 );
4027
4028 self.send_message(&msg);
4029 }
4030
4031 fn send_open_result(
4032 &mut self,
4033 channel_id: ChannelId,
4034 open_request: &OpenRequest,
4035 result: i32,
4036 target: MessageTarget,
4037 ) {
4038 self.send_message_with_target(
4039 &protocol::OpenResult {
4040 channel_id,
4041 open_id: open_request.open_id,
4042 status: result as u32,
4043 },
4044 target,
4045 );
4046 }
4047
4048 fn send_gpadl_created(&mut self, channel_id: ChannelId, gpadl_id: GpadlId, status: i32) {
4049 self.send_message(&protocol::GpadlCreated {
4050 channel_id,
4051 gpadl_id,
4052 status,
4053 });
4054 }
4055
4056 fn send_gpadl_torndown(&mut self, gpadl_id: GpadlId) {
4057 self.send_message(&protocol::GpadlTorndown { gpadl_id });
4058 }
4059
4060 fn send_rescind(&mut self, info: &OfferedInfo) {
4061 tracing::info!(
4062 channel_id = info.channel_id.0,
4063 "rescinding channel from guest"
4064 );
4065
4066 self.send_message(&protocol::RescindChannelOffer {
4067 channel_id: info.channel_id,
4068 });
4069 }
4070}
4071
4072struct VersionResponseData {
4074 version: VersionInfo,
4075 state: protocol::ConnectionState,
4076 monitor_pages: Option<MonitorPageGpas>,
4077}
4078
4079impl VersionResponseData {
4080 fn new(version: VersionInfo, state: protocol::ConnectionState) -> Self {
4082 VersionResponseData {
4083 version,
4084 state,
4085 monitor_pages: None,
4086 }
4087 }
4088
4089 fn with_monitor_pages(mut self, monitor_pages: Option<MonitorPageGpas>) -> Self {
4091 self.monitor_pages = monitor_pages;
4092 self
4093 }
4094}