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 offer_order = offer.offer_order;
1881 let channel = Channel {
1882 info: None,
1883 offer,
1884 state,
1885 restore_state: RestoreState::New,
1886 };
1887
1888 let offer_id = self.inner.channels.offer(channel);
1889 if let Some(info) = connected_info {
1890 let channel = &mut self.inner.channels[offer_id];
1891 channel.prepare_channel(
1892 offer_id,
1893 &mut self.inner.assigned_channels,
1894 &mut self.inner.assigned_monitors,
1895 );
1896
1897 self.inner
1898 .pending_messages
1899 .sender(self.notifier, self.inner.state.is_paused())
1900 .send_offer(channel, info);
1901 }
1902
1903 tracing::info!(?offer_id, ?offer_order, %key, confidential_ring_buffer, confidential_external_memory, "new channel");
1904 Ok(offer_id)
1905 }
1906
1907 pub fn revoke_channel(&mut self, offer_id: OfferId) {
1909 let channel = &mut self.inner.channels[offer_id];
1910 let retain = revoke(
1911 self.inner
1912 .pending_messages
1913 .sender(self.notifier, self.inner.state.is_paused()),
1914 offer_id,
1915 channel,
1916 &mut self.inner.gpadls,
1917 );
1918 if !retain {
1919 self.inner.channels.remove(offer_id);
1920 }
1921
1922 self.check_disconnected();
1923 }
1924
1925 pub fn open_complete(&mut self, offer_id: OfferId, result: i32) {
1927 let channel = &mut self.inner.channels[offer_id];
1928 tracing::debug!(offer_id = offer_id.0, key = %channel.offer.key(), result, "open complete");
1929
1930 match channel.state {
1931 ChannelState::Opening {
1932 request,
1933 reserved_state,
1934 } => {
1935 let channel_id = channel.info.expect("assigned").channel_id;
1936 if result >= 0 {
1937 tracelimit::info_ratelimited!(
1938 offer_id = offer_id.0,
1939 channel_id = channel_id.0,
1940 key = %channel.offer.key(),
1941 result,
1942 "opened channel"
1943 );
1944 } else {
1945 tracelimit::error_ratelimited!(
1947 offer_id = offer_id.0,
1948 channel_id = channel_id.0,
1949 key = %channel.offer.key(),
1950 result,
1951 "failed to open channel"
1952 );
1953 }
1954
1955 self.inner
1956 .pending_messages
1957 .sender(self.notifier, self.inner.state.is_paused())
1958 .send_open_result(
1959 channel_id,
1960 &request,
1961 result,
1962 MessageTarget::for_offer(offer_id, &reserved_state),
1963 );
1964 channel.state = if result >= 0 {
1965 ChannelState::Open {
1966 params: request,
1967 modify_state: ModifyState::NotModifying,
1968 reserved_state,
1969 }
1970 } else {
1971 ChannelState::Closed
1972 };
1973 }
1974 ChannelState::OpeningClientRelease => {
1975 tracing::info!(
1976 offer_id = offer_id.0,
1977 key = %channel.offer.key(),
1978 result,
1979 "opened channel (client released)"
1980 );
1981
1982 if result >= 0 {
1983 channel.state = ChannelState::ClosingClientRelease;
1984 self.notifier.notify(offer_id, Action::Close);
1985 } else {
1986 channel.state = ChannelState::ClientReleased;
1987 self.check_disconnected();
1988 }
1989 }
1990
1991 ChannelState::ClientReleased
1992 | ChannelState::Closed
1993 | ChannelState::Open { .. }
1994 | ChannelState::Closing { .. }
1995 | ChannelState::ClosingReopen { .. }
1996 | ChannelState::Revoked
1997 | ChannelState::Reoffered
1998 | ChannelState::ClosingClientRelease => {
1999 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid open complete")
2000 }
2001 }
2002 }
2003
2004 fn are_channels_reset(&self, include_reserved: bool) -> bool {
2007 self.inner.gpadls.keys().all(|(_, offer_id)| {
2008 !include_reserved && self.inner.channels[*offer_id].state.is_reserved()
2009 }) && self.inner.channels.iter().all(|(_, channel)| {
2010 matches!(channel.state, ChannelState::ClientReleased)
2011 || (!include_reserved && channel.state.is_reserved())
2012 })
2013 }
2014
2015 fn check_disconnected(&mut self) {
2019 match self.inner.state {
2020 ConnectionState::Disconnecting {
2021 next_action,
2022 modify_sent: false,
2023 } => {
2024 if self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)) {
2025 self.notify_disconnect(next_action);
2026 }
2027 }
2028 ConnectionState::Disconnecting {
2029 modify_sent: true, ..
2030 }
2031 | ConnectionState::Disconnected
2032 | ConnectionState::Connected { .. }
2033 | ConnectionState::Connecting { .. } => (),
2034 }
2035 }
2036
2037 fn notify_disconnect(&mut self, next_action: ConnectionAction) {
2039 debug_assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2041 self.inner.state = ConnectionState::Disconnecting {
2042 next_action,
2043 modify_sent: true,
2044 };
2045
2046 self.notifier
2048 .modify_connection(ModifyConnectionRequest {
2049 monitor_page: Update::Reset,
2050 interrupt_page: Update::Reset,
2051 ..Default::default()
2052 })
2053 .expect("resetting state should not fail");
2054 }
2055
2056 fn is_resetting(&self) -> bool {
2059 matches!(
2060 &self.inner.state,
2061 ConnectionState::Connecting {
2062 next_action: ConnectionAction::Reset,
2063 ..
2064 } | ConnectionState::Disconnecting {
2065 next_action: ConnectionAction::Reset,
2066 ..
2067 }
2068 )
2069 }
2070
2071 pub fn close_complete(&mut self, offer_id: OfferId) {
2073 let channel = &mut self.inner.channels[offer_id];
2074 tracing::info!(offer_id = offer_id.0, key = %channel.offer.key(), "closed channel");
2075 match channel.state {
2076 ChannelState::Closing {
2077 reserved_state: Some(reserved_state),
2078 ..
2079 } => {
2080 channel.state = ChannelState::Closed;
2081 let channel_id = channel.info.expect("assigned").channel_id;
2082 self.send_close_reserved_channel_response(
2086 channel_id,
2087 offer_id,
2088 reserved_state.target,
2089 );
2090
2091 if !matches!(self.inner.state, ConnectionState::Connected { .. }) {
2092 let channel = &mut self.inner.channels[offer_id];
2094 if Self::client_release_channel(
2097 self.inner
2098 .pending_messages
2099 .sender(self.notifier, self.inner.state.is_paused()),
2100 offer_id,
2101 channel,
2102 &mut self.inner.gpadls,
2103 &mut self.inner.incomplete_gpadls,
2104 &mut self.inner.assigned_channels,
2105 &mut self.inner.assigned_monitors,
2106 None,
2107 false,
2108 ) {
2109 self.inner.channels.remove(offer_id);
2110 }
2111 }
2112 }
2113 ChannelState::Closing { .. } => {
2114 channel.state = ChannelState::Closed;
2115 }
2116 ChannelState::ClosingClientRelease => {
2117 channel.state = ChannelState::ClientReleased;
2118 self.check_disconnected();
2119 }
2120 ChannelState::ClosingReopen { request, .. } => {
2121 channel.state = ChannelState::Closed;
2122 self.open_channel(offer_id, &request, None);
2123 }
2124
2125 ChannelState::Closed
2126 | ChannelState::ClientReleased
2127 | ChannelState::Opening { .. }
2128 | ChannelState::Open { .. }
2129 | ChannelState::Revoked
2130 | ChannelState::Reoffered
2131 | ChannelState::OpeningClientRelease => {
2132 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid close complete")
2133 }
2134 }
2135 }
2136
2137 fn send_close_reserved_channel_response(
2138 &mut self,
2139 channel_id: ChannelId,
2140 offer_id: OfferId,
2141 target: ConnectionTarget,
2142 ) {
2143 self.sender().send_message_with_target(
2144 &protocol::CloseReservedChannelResponse { channel_id },
2145 MessageTarget::ReservedChannel(offer_id, target),
2146 );
2147 }
2148
2149 fn handle_initiate_contact(
2152 &mut self,
2153 input: &protocol::InitiateContact2,
2154 message: &SynicMessage,
2155 includes_client_id: bool,
2156 ) -> Result<(), ChannelError> {
2157 let target_info =
2158 protocol::TargetInfo::from(input.initiate_contact.interrupt_page_or_target_info);
2159
2160 let target_sint = if message.multiclient
2161 && input.initiate_contact.version_requested >= Version::Win10Rs3_1 as u32
2162 {
2163 target_info.sint()
2164 } else {
2165 VMBUS_SINT
2166 };
2167
2168 let target_vtl = if message.multiclient
2169 && input.initiate_contact.version_requested >= Version::Win10Rs4 as u32
2170 {
2171 target_info.vtl()
2172 } else {
2173 0
2174 };
2175
2176 let feature_flags = if input.initiate_contact.version_requested >= Version::Copper as u32 {
2177 target_info.feature_flags()
2178 } else {
2179 0
2180 };
2181
2182 let target_message_vp =
2187 if input.initiate_contact.version_requested >= Version::Win8_1 as u32 {
2188 input.initiate_contact.target_message_vp
2189 } else {
2190 0
2191 };
2192
2193 let interrupt_page = (input.initiate_contact.version_requested < Version::Win8 as u32
2200 && input.initiate_contact.interrupt_page_or_target_info != 0)
2201 .then_some(input.initiate_contact.interrupt_page_or_target_info);
2202
2203 let monitor_page = if (input.initiate_contact.parent_to_child_monitor_page_gpa == 0)
2206 != (input.initiate_contact.child_to_parent_monitor_page_gpa == 0)
2207 {
2208 MonitorPageRequest::Invalid
2209 } else if input.initiate_contact.parent_to_child_monitor_page_gpa != 0 {
2210 MonitorPageRequest::Some(MonitorPageGpas {
2211 parent_to_child: input.initiate_contact.parent_to_child_monitor_page_gpa,
2212 child_to_parent: input.initiate_contact.child_to_parent_monitor_page_gpa,
2213 })
2214 } else {
2215 MonitorPageRequest::None
2216 };
2217
2218 let client_id = if FeatureFlags::from(feature_flags).client_id() {
2221 if includes_client_id {
2222 input.client_id
2223 } else {
2224 return Err(ChannelError::ParseError(
2225 protocol::ParseError::MessageTooSmall(Some(
2226 protocol::MessageType::INITIATE_CONTACT,
2227 )),
2228 ));
2229 }
2230 } else {
2231 Guid::ZERO
2232 };
2233
2234 let request = InitiateContactRequest {
2235 version_requested: input.initiate_contact.version_requested,
2236 target_message_vp,
2237 monitor_page,
2238 target_sint,
2239 target_vtl,
2240 feature_flags,
2241 interrupt_page,
2242 client_id,
2243 trusted: message.trusted,
2244 };
2245 self.initiate_contact(request);
2246 Ok(())
2247 }
2248
2249 pub fn initiate_contact(&mut self, request: InitiateContactRequest) {
2250 let vtl = self.inner.assigned_channels.vtl as u8;
2253 if request.target_vtl != vtl {
2254 self.notifier.forward_unhandled(request);
2256 return;
2257 }
2258
2259 if request.target_sint != VMBUS_SINT {
2260 tracelimit::warn_ratelimited!(
2261 target_vtl = request.target_vtl,
2262 target_sint = request.target_sint,
2263 version = request.version_requested,
2264 "unsupported multiclient request",
2265 );
2266
2267 self.send_version_response_with_target(
2269 None,
2270 MessageTarget::Custom(ConnectionTarget {
2271 vp: request.target_message_vp,
2272 sint: request.target_sint,
2273 }),
2274 );
2275
2276 return;
2277 }
2278
2279 if !self.request_disconnect(ConnectionAction::Reconnect {
2280 initiate_contact: request,
2281 }) {
2282 return;
2283 }
2284
2285 let Some(version) = self.check_version_supported(&request) else {
2286 tracelimit::warn_ratelimited!(
2287 vtl,
2288 version = request.version_requested,
2289 client_id = ?request.client_id,
2290 "Guest requested unsupported version"
2291 );
2292
2293 self.send_version_response(None);
2295 return;
2296 };
2297
2298 let monitor_page = match request.monitor_page {
2301 MonitorPageRequest::Some(mp) => {
2302 if self.inner.require_server_allocated_mnf {
2303 if !version.feature_flags.server_specified_monitor_pages() {
2304 tracelimit::warn_ratelimited!(
2305 "guest-supplied monitor pages not supported; MNF will be disabled"
2306 );
2307 }
2308
2309 None
2310 } else {
2311 Some(mp)
2312 }
2313 }
2314 MonitorPageRequest::None => None,
2315 MonitorPageRequest::Invalid => {
2316 self.send_version_response(Some(VersionResponseData::new(
2318 version,
2319 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2320 )));
2321
2322 return;
2323 }
2324 };
2325
2326 self.inner.state = ConnectionState::Connecting {
2327 info: ConnectionInfo {
2328 version,
2329 trusted: request.trusted,
2330 interrupt_page: request.interrupt_page,
2331 monitor_page: monitor_page.map(MonitorPageGpaInfo::from_guest_gpas),
2332 target_message_vp: request.target_message_vp,
2333 modifying: false,
2334 offers_sent: false,
2335 client_id: request.client_id,
2336 paused: false,
2337 },
2338 next_action: ConnectionAction::None,
2339 };
2340
2341 if let Err(err) = self.notifier.modify_connection(ModifyConnectionRequest {
2344 version: Some(version),
2345 monitor_page: monitor_page.into(),
2346 interrupt_page: request.interrupt_page.into(),
2347 target_message_vp: Some(request.target_message_vp),
2348 notify_relay: true,
2349 }) {
2350 tracelimit::error_ratelimited!(?err, "server failed to change state");
2351 self.inner.state = ConnectionState::Disconnected;
2352 self.send_version_response(Some(VersionResponseData::new(
2353 version,
2354 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2355 )));
2356 }
2357 }
2358
2359 pub(crate) fn complete_initiate_contact(&mut self, response: ModifyConnectionResponse) {
2360 let ConnectionState::Connecting {
2361 mut info,
2362 next_action,
2363 } = self.inner.state
2364 else {
2365 panic!("Invalid state for completing InitiateContact.");
2366 };
2367
2368 const LOCAL_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
2372 .with_client_id(true)
2373 .with_confidential_channels(true)
2374 .with_gpa_pinning(true);
2375
2376 let (relay_feature_flags, server_specified_monitor_page) = match response {
2377 ModifyConnectionResponse::Supported(
2379 protocol::ConnectionState::SUCCESSFUL,
2380 feature_flags,
2381 server_specified_monitor_page,
2382 ) => (feature_flags, server_specified_monitor_page),
2383 ModifyConnectionResponse::Supported(
2386 connection_state,
2387 feature_flags,
2388 server_specified_monitor_page,
2389 ) => {
2390 tracelimit::error_ratelimited!(
2391 ?connection_state,
2392 "initiate contact failed because relay request failed"
2393 );
2394
2395 info.version.feature_flags &= (feature_flags | LOCAL_FEATURE_FLAGS)
2398 .with_server_specified_monitor_pages(server_specified_monitor_page.is_some());
2399
2400 self.send_version_response(Some(VersionResponseData::new(
2401 info.version,
2402 connection_state,
2403 )));
2404 self.inner.state = ConnectionState::Disconnected;
2405 return;
2406 }
2407 ModifyConnectionResponse::Unsupported => {
2410 self.send_version_response(None);
2411 self.inner.state = ConnectionState::Disconnected;
2412 return;
2413 }
2414 ModifyConnectionResponse::Modified(_) => {
2415 panic!("Invalid response for completing InitiateContact.");
2416 }
2417 };
2418
2419 assert!(
2421 info.version.feature_flags.server_specified_monitor_pages()
2422 || server_specified_monitor_page.is_none()
2423 );
2424
2425 info.version.feature_flags &= relay_feature_flags | LOCAL_FEATURE_FLAGS;
2428
2429 if let Some(gpas) = server_specified_monitor_page {
2433 info.monitor_page = Some(MonitorPageGpaInfo::from_server_gpas(gpas));
2434 info.version
2435 .feature_flags
2436 .set_server_specified_monitor_pages(true);
2437 } else {
2438 info.version
2439 .feature_flags
2440 .set_server_specified_monitor_pages(false);
2441 }
2442
2443 tracelimit::info_ratelimited!(
2444 vtl = self.inner.assigned_channels.vtl as u8,
2445 version = ?info.version,
2446 client_id = ?info.client_id,
2447 trusted = info.trusted,
2448 "guest negotiated version"
2449 );
2450
2451 let version = info.version;
2452 self.inner.state = ConnectionState::Connected(info);
2453
2454 self.send_version_response(Some(
2455 VersionResponseData::new(version, protocol::ConnectionState::SUCCESSFUL)
2456 .with_monitor_pages(server_specified_monitor_page),
2457 ));
2458 if !matches!(next_action, ConnectionAction::None) && self.request_disconnect(next_action) {
2459 self.do_next_action(next_action);
2460 }
2461 }
2462
2463 fn check_version_supported(&self, request: &InitiateContactRequest) -> Option<VersionInfo> {
2465 let version = SUPPORTED_VERSIONS
2466 .iter()
2467 .find(|v| request.version_requested == **v as u32)
2468 .copied()?;
2469
2470 if let Some(max_version) = self.inner.max_version {
2472 if version as u32 > max_version.version {
2473 return None;
2474 }
2475 }
2476
2477 let supported_flags = if version >= Version::Copper {
2478 let max_supported_flags = SUPPORTED_FEATURE_FLAGS
2480 .with_confidential_channels(request.trusted)
2481 .with_gpa_pinning(self.inner.support_gpa_pinning);
2482
2483 if let Some(max_version) = self.inner.max_version {
2485 max_supported_flags & max_version.feature_flags
2486 } else {
2487 max_supported_flags
2488 }
2489 } else {
2490 FeatureFlags::new()
2491 };
2492
2493 let feature_flags = supported_flags & request.feature_flags.into();
2494
2495 assert!(version >= Version::Copper || feature_flags == FeatureFlags::new());
2496 if feature_flags.into_bits() != request.feature_flags {
2497 tracelimit::info_ratelimited!(
2500 supported = feature_flags.into_bits(),
2501 requested = request.feature_flags,
2502 "guest requested unsupported feature flags."
2503 );
2504 }
2505
2506 Some(VersionInfo {
2507 version,
2508 feature_flags,
2509 })
2510 }
2511
2512 fn send_version_response(&mut self, data: Option<VersionResponseData>) {
2513 self.send_version_response_with_target(data, MessageTarget::Default);
2514 }
2515
2516 fn send_version_response_with_target(
2517 &mut self,
2518 data: Option<VersionResponseData>,
2519 target: MessageTarget,
2520 ) {
2521 enum VersionResponseType {
2522 PreCopper,
2523 Copper,
2524 CopperWithServerMnf,
2525 }
2526
2527 let mut response_copper_with_mnf = protocol::VersionResponse3::new_zeroed();
2528 let response_copper = &mut response_copper_with_mnf.version_response2;
2529 let response = &mut response_copper.version_response;
2530 let mut response_type = VersionResponseType::PreCopper;
2531 if let Some(data) = data {
2532 if data.state == protocol::ConnectionState::SUCCESSFUL
2535 || data.version.version >= Version::Win8
2536 {
2537 response.version_supported = 1;
2538 response.connection_state = data.state;
2539 response.selected_version_or_connection_id =
2540 if data.version.version >= Version::Win10Rs3_1 {
2541 self.inner.child_connection_id
2542 } else {
2543 data.version.version as u32
2544 };
2545
2546 if data.version.version >= Version::Copper {
2547 response_copper.supported_features = data.version.feature_flags.into();
2548 response_type = VersionResponseType::Copper;
2549 if let Some(monitor_page) = data.monitor_pages {
2550 assert!(data.version.feature_flags.server_specified_monitor_pages());
2551 response_copper_with_mnf.child_to_parent_monitor_page_gpa =
2552 monitor_page.child_to_parent;
2553 response_copper_with_mnf.parent_to_child_monitor_page_gpa =
2554 monitor_page.parent_to_child;
2555 response_type = VersionResponseType::CopperWithServerMnf;
2556 }
2557 }
2558 }
2559 }
2560
2561 match response_type {
2563 VersionResponseType::PreCopper => {
2564 self.sender().send_message_with_target(response, target)
2565 }
2566 VersionResponseType::Copper => self
2567 .sender()
2568 .send_message_with_target(response_copper, target),
2569 VersionResponseType::CopperWithServerMnf => self
2570 .sender()
2571 .send_message_with_target(&response_copper_with_mnf, target),
2572 }
2573 }
2574
2575 fn request_disconnect(&mut self, new_action: ConnectionAction) -> bool {
2578 assert!(!self.is_resetting());
2579
2580 let gpadls = &mut self.inner.gpadls;
2582 let vm_reset = matches!(new_action, ConnectionAction::Reset);
2583 self.inner.channels.retain(|offer_id, channel| {
2584 (!vm_reset && channel.state.is_reserved())
2586 || !Self::client_release_channel(
2587 self.inner
2588 .pending_messages
2589 .sender(self.notifier, self.inner.state.is_paused()),
2590 offer_id,
2591 channel,
2592 gpadls,
2593 &mut self.inner.incomplete_gpadls,
2594 &mut self.inner.assigned_channels,
2595 &mut self.inner.assigned_monitors,
2596 None,
2597 vm_reset,
2598 )
2599 });
2600
2601 match &mut self.inner.state {
2605 ConnectionState::Disconnected => {
2606 if vm_reset {
2608 if !self.are_channels_reset(true) {
2609 self.inner.state = ConnectionState::Disconnecting {
2610 next_action: ConnectionAction::Reset,
2611 modify_sent: false,
2612 };
2613 }
2614 } else {
2615 assert!(self.are_channels_reset(false));
2616 }
2617 }
2618
2619 ConnectionState::Connected { .. } => {
2620 if self.are_channels_reset(vm_reset) {
2621 self.notify_disconnect(new_action);
2622 } else {
2623 self.inner.state = ConnectionState::Disconnecting {
2624 next_action: new_action,
2625 modify_sent: false,
2626 };
2627 }
2628 }
2629
2630 ConnectionState::Connecting { next_action, .. }
2631 | ConnectionState::Disconnecting { next_action, .. } => {
2632 *next_action = new_action;
2633 }
2634 }
2635
2636 matches!(self.inner.state, ConnectionState::Disconnected)
2637 }
2638
2639 pub(crate) fn complete_disconnect(&mut self) {
2640 if let ConnectionState::Disconnecting {
2641 next_action,
2642 modify_sent,
2643 } = std::mem::replace(&mut self.inner.state, ConnectionState::Disconnected)
2644 {
2645 assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2646 if !modify_sent {
2647 tracelimit::warn_ratelimited!("unexpected modify response");
2648 }
2649
2650 self.inner.state = ConnectionState::Disconnected;
2651 self.do_next_action(next_action);
2652 } else {
2653 unreachable!("not ready for disconnect");
2654 }
2655 }
2656
2657 fn do_next_action(&mut self, action: ConnectionAction) {
2658 match action {
2659 ConnectionAction::None => {}
2660 ConnectionAction::Reset => {
2661 self.complete_reset();
2662 }
2663 ConnectionAction::SendUnloadComplete => {
2664 self.complete_unload();
2665 }
2666 ConnectionAction::Reconnect { initiate_contact } => {
2667 self.initiate_contact(initiate_contact);
2668 }
2669 ConnectionAction::SendFailedVersionResponse => {
2670 self.send_version_response(None);
2673 }
2674 }
2675 }
2676
2677 fn handle_unload(&mut self) {
2679 tracing::debug!(
2680 vtl = self.inner.assigned_channels.vtl as u8,
2681 state = ?self.inner.state,
2682 "VmBus received unload request from guest",
2683 );
2684
2685 if self.request_disconnect(ConnectionAction::SendUnloadComplete) {
2686 self.complete_unload();
2687 }
2688 }
2689
2690 fn complete_unload(&mut self) {
2691 self.notifier.unload_complete();
2692 if let Some(version) = self.inner.delayed_max_version.take() {
2693 self.inner.set_compatibility_version(version, false);
2694 }
2695
2696 self.sender().send_message(&protocol::UnloadComplete {});
2697 tracelimit::info_ratelimited!("Vmbus disconnected");
2698 }
2699
2700 fn handle_request_offers(&mut self) -> Result<(), ChannelError> {
2702 let ConnectionState::Connected(info) = &mut self.inner.state else {
2703 unreachable!(
2704 "in unexpected state {:?}, should be prevented by Message::parse()",
2705 self.inner.state
2706 );
2707 };
2708
2709 if info.offers_sent {
2710 return Err(ChannelError::OffersAlreadySent);
2711 }
2712
2713 info.offers_sent = true;
2714
2715 let mut sorted_channels: Vec<_> = self
2718 .inner
2719 .channels
2720 .iter_mut()
2721 .filter(|(_, channel)| !channel.state.is_reserved())
2722 .collect();
2723
2724 if self.inner.use_absolute_channel_order {
2725 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2726 (
2727 channel.offer.offer_order.unwrap_or(u64::MAX),
2728 channel.offer.interface_id,
2729 channel.offer.instance_id,
2730 )
2731 });
2732 } else {
2733 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2734 (
2735 channel.offer.interface_id,
2736 channel.offer.offer_order.unwrap_or(u64::MAX),
2737 channel.offer.instance_id,
2738 )
2739 });
2740 }
2741
2742 for (offer_id, channel) in sorted_channels {
2743 assert!(matches!(channel.state, ChannelState::ClientReleased));
2744
2745 channel.prepare_channel(
2746 offer_id,
2747 &mut self.inner.assigned_channels,
2748 &mut self.inner.assigned_monitors,
2749 );
2750
2751 channel.state = ChannelState::Closed;
2752 self.inner
2753 .pending_messages
2754 .sender(self.notifier, info.paused)
2755 .send_offer(channel, info);
2756 }
2757 self.sender().send_message(&protocol::AllOffersDelivered {});
2758
2759 Ok(())
2760 }
2761
2762 fn gpadl_completed(
2764 mut sender: MessageSender<'_, N>,
2765 offer_id: OfferId,
2766 channel: &Channel,
2767 gpadl_id: GpadlId,
2768 gpadl: &mut Gpadl,
2769 ) {
2770 if channel.state.is_revoked() {
2771 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2772
2773 gpadl.state = GpadlState::Accepted;
2777 sender.send_gpadl_created(channel_id, gpadl_id, protocol::STATUS_SUCCESS);
2778 } else {
2779 sender.notifier.notify(
2781 offer_id,
2782 Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
2783 );
2784 }
2785 }
2786
2787 fn handle_gpadl_header_core(
2789 &mut self,
2790 input: &protocol::GpadlHeader,
2791 range: &[u8],
2792 ) -> Result<(), ChannelError> {
2793 let (offer_id, channel) = self
2795 .inner
2796 .channels
2797 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2798
2799 if channel.state.is_reserved() {
2802 return Err(ChannelError::ChannelReserved);
2803 }
2804
2805 let mut gpadl = Gpadl::new(input.count, input.len as usize / 8);
2807 let done = gpadl.append(range)?;
2808
2809 let gpadl = match self.inner.gpadls.entry((input.gpadl_id, offer_id)) {
2811 Entry::Vacant(entry) => entry.insert(gpadl),
2812 Entry::Occupied(_) => return Err(ChannelError::DuplicateGpadlId),
2813 };
2814
2815 if done {
2816 Self::gpadl_completed(
2817 self.inner
2818 .pending_messages
2819 .sender(self.notifier, self.inner.state.is_paused()),
2820 offer_id,
2821 channel,
2822 input.gpadl_id,
2823 gpadl,
2824 )
2825 } else {
2826 match self.inner.incomplete_gpadls.entry(input.gpadl_id) {
2832 Entry::Vacant(entry) => {
2833 entry.insert(offer_id);
2834 }
2835 Entry::Occupied(_) => {
2836 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2837 tracelimit::error_ratelimited!(
2838 channel_id = ?input.channel_id,
2839 key = %channel.offer.key(),
2840 gpadl_id = ?input.gpadl_id,
2841 "duplicate in-progress gpadl ID",
2842 );
2843 return Err(ChannelError::DuplicateGpadlId);
2844 }
2845 }
2846 }
2847 Ok(())
2848 }
2849
2850 fn handle_gpadl_header(&mut self, input: &protocol::GpadlHeader, range: &[u8]) {
2852 if let Err(err) = self.handle_gpadl_header_core(input, range) {
2853 tracelimit::warn_ratelimited!(
2854 err = &err as &dyn std::error::Error,
2855 channel_id = ?input.channel_id,
2856 key = %self.inner.channels.get_by_channel_id(&self.inner.assigned_channels, input.channel_id).map(|(_, c)| c.offer.key()).unwrap_or_default(),
2857 gpadl_id = ?input.gpadl_id,
2858 "error handling gpadl header"
2859 );
2860
2861 self.sender().send_gpadl_created(
2863 input.channel_id,
2864 input.gpadl_id,
2865 protocol::STATUS_UNSUCCESSFUL,
2866 );
2867 }
2868 }
2869
2870 fn handle_gpadl_body(
2876 &mut self,
2877 input: &protocol::GpadlBody,
2878 range: &[u8],
2879 ) -> Result<(), ChannelError> {
2880 let &offer_id = self
2884 .inner
2885 .incomplete_gpadls
2886 .get(&input.gpadl_id)
2887 .ok_or(ChannelError::UnknownGpadlId)?;
2888 let gpadl = self
2889 .inner
2890 .gpadls
2891 .get_mut(&(input.gpadl_id, offer_id))
2892 .ok_or(ChannelError::UnknownGpadlId)?;
2893 let channel = &mut self.inner.channels[offer_id];
2894
2895 match gpadl.append(range) {
2896 Ok(done) => {
2897 if done {
2898 self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2899 Self::gpadl_completed(
2900 self.inner
2901 .pending_messages
2902 .sender(self.notifier, self.inner.state.is_paused()),
2903 offer_id,
2904 channel,
2905 input.gpadl_id,
2906 gpadl,
2907 )
2908 }
2909 }
2910 Err(err) => {
2911 self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2912 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2913 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2914 tracelimit::warn_ratelimited!(
2915 err = &err as &dyn std::error::Error,
2916 channel_id = channel_id.0,
2917 key = %channel.offer.key(),
2918 gpadl_id = input.gpadl_id.0,
2919 "error handling gpadl body"
2920 );
2921 self.sender().send_gpadl_created(
2922 channel_id,
2923 input.gpadl_id,
2924 protocol::STATUS_UNSUCCESSFUL,
2925 );
2926 }
2927 }
2928
2929 Ok(())
2930 }
2931
2932 fn handle_gpadl_teardown(
2934 &mut self,
2935 input: &protocol::GpadlTeardown,
2936 ) -> Result<(), ChannelError> {
2937 let (offer_id, channel) = self
2938 .inner
2939 .channels
2940 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2941
2942 tracing::debug!(
2943 channel_id = input.channel_id.0,
2944 key = %channel.offer.key(),
2945 gpadl_id = input.gpadl_id.0,
2946 "Received GPADL teardown request"
2947 );
2948
2949 let gpadl = self
2950 .inner
2951 .gpadls
2952 .get_mut(&(input.gpadl_id, offer_id))
2953 .ok_or(ChannelError::UnknownGpadlId)?;
2954
2955 match gpadl.state {
2956 GpadlState::InProgress
2957 | GpadlState::Offered
2958 | GpadlState::OfferedTearingDown
2959 | GpadlState::TearingDown => {
2960 return Err(ChannelError::InvalidGpadlState);
2961 }
2962 GpadlState::Accepted => {
2963 if channel.info.as_ref().map(|info| info.channel_id) != Some(input.channel_id) {
2964 return Err(ChannelError::WrongGpadlChannelId);
2965 }
2966
2967 if channel.state.is_reserved() {
2971 return Err(ChannelError::ChannelReserved);
2972 }
2973
2974 if channel.state.is_revoked() {
2975 tracing::trace!(
2976 channel_id = input.channel_id.0,
2977 key = %channel.offer.key(),
2978 gpadl_id = input.gpadl_id.0,
2979 "Gpadl teardown for revoked channel"
2980 );
2981
2982 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2983 self.sender().send_gpadl_torndown(input.gpadl_id);
2984 } else {
2985 gpadl.state = GpadlState::TearingDown;
2986 self.notifier.notify(
2987 offer_id,
2988 Action::TeardownGpadl {
2989 gpadl_id: input.gpadl_id,
2990 post_restore: false,
2991 },
2992 );
2993 }
2994 }
2995 }
2996 Ok(())
2997 }
2998
2999 fn open_channel(
3002 &mut self,
3003 offer_id: OfferId,
3004 input: &OpenRequest,
3005 reserved_state: Option<ReservedState>,
3006 ) {
3007 let channel = &mut self.inner.channels[offer_id];
3008 assert!(matches!(channel.state, ChannelState::Closed));
3009
3010 channel.state = ChannelState::Opening {
3011 request: *input,
3012 reserved_state,
3013 };
3014
3015 let info = channel.info.as_ref().expect("assigned");
3018 self.notifier.notify(
3019 offer_id,
3020 Action::Open(
3021 OpenParams::from_request(
3022 info,
3023 input,
3024 channel.handled_monitor_info(),
3025 reserved_state.map(|state| state.target),
3026 ),
3027 self.inner.state.get_version().expect("must be connected"),
3028 ),
3029 );
3030 }
3031
3032 fn handle_open_channel(&mut self, input: &protocol::OpenChannel2) -> Result<(), ChannelError> {
3034 let (offer_id, channel) = self
3035 .inner
3036 .channels
3037 .get_by_channel_id_mut(&self.inner.assigned_channels, input.open_channel.channel_id)?;
3038
3039 let guest_specified_interrupt_info = self
3040 .inner
3041 .state
3042 .check_feature_flags(|ff| ff.guest_specified_signal_parameters())
3043 .then_some(SignalInfo {
3044 event_flag: input.event_flag,
3045 connection_id: input.connection_id,
3046 });
3047
3048 let flags = if self
3049 .inner
3050 .state
3051 .check_feature_flags(|ff| ff.channel_interrupt_redirection())
3052 {
3053 input.flags
3054 } else {
3055 Default::default()
3056 };
3057
3058 let request = OpenRequest {
3059 open_id: input.open_channel.open_id,
3060 ring_buffer_gpadl_id: input.open_channel.ring_buffer_gpadl_id,
3061 target_vp: protocol::vp_index_if_enabled(input.open_channel.target_vp),
3062 downstream_ring_buffer_page_offset: input
3063 .open_channel
3064 .downstream_ring_buffer_page_offset,
3065 user_data: input.open_channel.user_data,
3066 guest_specified_interrupt_info,
3067 flags,
3068 };
3069
3070 match channel.state {
3071 ChannelState::Closed => self.open_channel(offer_id, &request, None),
3072 ChannelState::Closing { params, .. } => {
3073 channel.state = ChannelState::ClosingReopen { params, request }
3077 }
3078 ChannelState::Revoked | ChannelState::Reoffered => {}
3079
3080 ChannelState::Open { .. }
3081 | ChannelState::Opening { .. }
3082 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelAlreadyOpen),
3083
3084 ChannelState::ClientReleased
3085 | ChannelState::ClosingClientRelease
3086 | ChannelState::OpeningClientRelease => unreachable!(),
3087 }
3088 Ok(())
3089 }
3090
3091 fn handle_close_channel(&mut self, input: &protocol::CloseChannel) -> Result<(), ChannelError> {
3093 let (offer_id, channel) = self
3094 .inner
3095 .channels
3096 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3097
3098 match channel.state {
3099 ChannelState::Open {
3100 params,
3101 modify_state,
3102 reserved_state: None,
3103 } => {
3104 if modify_state.is_modifying() {
3105 tracelimit::warn_ratelimited!(
3106 key = %channel.offer.key(),
3107 ?modify_state,
3108 "Client is closing the channel with a modify in progress"
3109 )
3110 }
3111
3112 channel.state = ChannelState::Closing {
3113 params,
3114 reserved_state: None,
3115 };
3116 self.notifier.notify(offer_id, Action::Close);
3117 }
3118
3119 ChannelState::Open {
3120 reserved_state: Some(_),
3121 ..
3122 } => return Err(ChannelError::ChannelReserved),
3123
3124 ChannelState::Revoked | ChannelState::Reoffered => {}
3125
3126 ChannelState::Closed
3127 | ChannelState::Opening { .. }
3128 | ChannelState::Closing { .. }
3129 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3130
3131 ChannelState::ClientReleased
3132 | ChannelState::ClosingClientRelease
3133 | ChannelState::OpeningClientRelease => unreachable!(),
3134 }
3135
3136 Ok(())
3137 }
3138
3139 fn handle_open_reserved_channel(
3142 &mut self,
3143 input: &protocol::OpenReservedChannel,
3144 version: VersionInfo,
3145 ) -> Result<(), ChannelError> {
3146 let (offer_id, channel) = self
3147 .inner
3148 .channels
3149 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3150
3151 let target = ConnectionTarget {
3152 vp: input.target_vp,
3153 sint: input.target_sint as u8,
3154 };
3155
3156 let reserved_state = Some(ReservedState { version, target });
3157
3158 let request = OpenRequest {
3159 ring_buffer_gpadl_id: input.ring_buffer_gpadl,
3160 target_vp: None,
3162 downstream_ring_buffer_page_offset: input.downstream_page_offset,
3163 open_id: 0,
3164 user_data: UserDefinedData::new_zeroed(),
3165 guest_specified_interrupt_info: None,
3166 flags: Default::default(),
3167 };
3168
3169 match channel.state {
3170 ChannelState::Closed => self.open_channel(offer_id, &request, reserved_state),
3171 ChannelState::Revoked | ChannelState::Reoffered => {}
3172
3173 ChannelState::Open { .. } | ChannelState::Opening { .. } => {
3174 return Err(ChannelError::ChannelAlreadyOpen);
3175 }
3176
3177 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3178 return Err(ChannelError::InvalidChannelState);
3179 }
3180
3181 ChannelState::ClientReleased
3182 | ChannelState::ClosingClientRelease
3183 | ChannelState::OpeningClientRelease => unreachable!(),
3184 }
3185 Ok(())
3186 }
3187
3188 fn handle_close_reserved_channel(
3191 &mut self,
3192 input: &protocol::CloseReservedChannel,
3193 ) -> Result<(), ChannelError> {
3194 let (offer_id, channel) = self
3195 .inner
3196 .channels
3197 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3198
3199 match channel.state {
3200 ChannelState::Open {
3201 params,
3202 reserved_state: Some(mut resvd),
3203 ..
3204 } => {
3205 resvd.target.vp = input.target_vp;
3206 resvd.target.sint = input.target_sint as u8;
3207 channel.state = ChannelState::Closing {
3208 params,
3209 reserved_state: Some(resvd),
3210 };
3211 self.notifier.notify(offer_id, Action::Close);
3212 }
3213
3214 ChannelState::Open {
3215 reserved_state: None,
3216 ..
3217 } => return Err(ChannelError::ChannelNotReserved),
3218
3219 ChannelState::Revoked | ChannelState::Reoffered => {}
3220
3221 ChannelState::Closed
3222 | ChannelState::Opening { .. }
3223 | ChannelState::Closing { .. }
3224 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3225
3226 ChannelState::ClientReleased
3227 | ChannelState::ClosingClientRelease
3228 | ChannelState::OpeningClientRelease => unreachable!(),
3229 }
3230
3231 Ok(())
3232 }
3233
3234 #[must_use]
3238 fn client_release_channel(
3239 mut sender: MessageSender<'_, N>,
3240 offer_id: OfferId,
3241 channel: &mut Channel,
3242 gpadls: &mut GpadlMap,
3243 incomplete_gpadls: &mut IncompleteGpadlMap,
3244 assigned_channels: &mut AssignedChannels,
3245 assigned_monitors: &mut AssignedMonitors,
3246 info: Option<&ConnectionInfo>,
3247 vm_reset: bool,
3248 ) -> bool {
3249 tracelimit::info_ratelimited!(?offer_id, key = %channel.offer.key(), "client released channel");
3250 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3252 if gpadl_offer_id != offer_id {
3253 return true;
3254 }
3255 match gpadl.state {
3256 GpadlState::InProgress => {
3257 incomplete_gpadls.remove(&gpadl_id);
3258 false
3259 }
3260 GpadlState::Offered => {
3261 gpadl.state = GpadlState::OfferedTearingDown;
3262 true
3263 }
3264 GpadlState::Accepted => {
3265 if channel.state.is_revoked() {
3266 false
3268 } else {
3269 gpadl.state = GpadlState::TearingDown;
3270 sender.notifier.notify(
3271 offer_id,
3272 Action::TeardownGpadl {
3273 gpadl_id,
3274 post_restore: false,
3275 },
3276 );
3277 true
3278 }
3279 }
3280 GpadlState::OfferedTearingDown | GpadlState::TearingDown => true,
3281 }
3282 });
3283
3284 let remove = match &mut channel.state {
3285 ChannelState::Closed => {
3286 channel.state = ChannelState::ClientReleased;
3287 false
3288 }
3289 ChannelState::Reoffered => {
3290 if let Some(info) = info {
3291 channel.state = ChannelState::Closed;
3292 channel.restore_state = RestoreState::New;
3293 sender.send_offer(channel, info);
3294 return false;
3296 }
3297 channel.state = ChannelState::ClientReleased;
3298 false
3299 }
3300 ChannelState::Revoked => {
3301 channel.state = ChannelState::ClientReleased;
3302 true
3303 }
3304 ChannelState::Opening { .. } => {
3305 if vm_reset {
3323 channel.state = ChannelState::ClientReleased;
3324 } else {
3325 channel.state = ChannelState::OpeningClientRelease;
3326 }
3327 false
3328 }
3329 ChannelState::Open { .. } => {
3330 channel.state = ChannelState::ClosingClientRelease;
3331 sender.notifier.notify(offer_id, Action::Close);
3332 false
3333 }
3334 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3335 channel.state = ChannelState::ClosingClientRelease;
3336 false
3337 }
3338
3339 ChannelState::ClosingClientRelease
3340 | ChannelState::OpeningClientRelease
3341 | ChannelState::ClientReleased => false,
3342 };
3343
3344 assert!(channel.state.is_released());
3345
3346 channel.release_channel(offer_id, assigned_channels, assigned_monitors);
3347 remove
3348 }
3349
3350 fn handle_rel_id_released(
3352 &mut self,
3353 input: &protocol::RelIdReleased,
3354 ) -> Result<(), ChannelError> {
3355 let channel_id = input.channel_id;
3356 let (offer_id, channel) = self
3357 .inner
3358 .channels
3359 .get_by_channel_id_mut(&self.inner.assigned_channels, channel_id)?;
3360
3361 match channel.state {
3362 ChannelState::Closed
3363 | ChannelState::Revoked
3364 | ChannelState::Closing { .. }
3365 | ChannelState::Reoffered => {
3366 if Self::client_release_channel(
3367 self.inner
3368 .pending_messages
3369 .sender(self.notifier, self.inner.state.is_paused()),
3370 offer_id,
3371 channel,
3372 &mut self.inner.gpadls,
3373 &mut self.inner.incomplete_gpadls,
3374 &mut self.inner.assigned_channels,
3375 &mut self.inner.assigned_monitors,
3376 self.inner.state.get_connected_info(),
3377 false,
3378 ) {
3379 self.inner.channels.remove(offer_id);
3380 }
3381
3382 self.check_disconnected();
3383 }
3384
3385 ChannelState::Opening { .. }
3386 | ChannelState::Open { .. }
3387 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::InvalidChannelState),
3388
3389 ChannelState::ClientReleased
3390 | ChannelState::OpeningClientRelease
3391 | ChannelState::ClosingClientRelease => unreachable!(),
3392 }
3393 Ok(())
3394 }
3395
3396 fn handle_tl_connect_request(&mut self, request: protocol::TlConnectRequest2) {
3399 let version = self
3400 .inner
3401 .state
3402 .get_version()
3403 .expect("must be connected")
3404 .version;
3405
3406 let hosted_silo_unaware = version < Version::Win10Rs5;
3407 self.notifier
3408 .notify_hvsock(&HvsockConnectRequest::from_message(
3409 request,
3410 hosted_silo_unaware,
3411 ));
3412 }
3413
3414 pub fn send_tl_connect_result(&mut self, result: HvsockConnectResult) {
3416 if !result.success && self.inner.state.check_version(Version::Win10Rs3_0) {
3420 self.sender().send_message(&protocol::TlConnectResult {
3424 service_id: result.service_id,
3425 endpoint_id: result.endpoint_id,
3426 status: protocol::STATUS_CONNECTION_REFUSED,
3427 })
3428 }
3429 }
3430
3431 fn handle_modify_channel(
3434 &mut self,
3435 request: &protocol::ModifyChannel,
3436 ) -> Result<(), ChannelError> {
3437 let result = self.modify_channel(request);
3438 if result.is_err() {
3439 self.send_modify_channel_response(request.channel_id, protocol::STATUS_UNSUCCESSFUL);
3440 }
3441
3442 result
3443 }
3444
3445 fn modify_channel(&mut self, request: &protocol::ModifyChannel) -> Result<(), ChannelError> {
3447 if request.target_vp == protocol::VP_INDEX_DISABLE_INTERRUPT {
3449 return Err(ChannelError::InvalidTargetVp);
3450 }
3451
3452 let (offer_id, channel) = self
3453 .inner
3454 .channels
3455 .get_by_channel_id_mut(&self.inner.assigned_channels, request.channel_id)?;
3456
3457 let (open_request, modify_state) = match &mut channel.state {
3458 ChannelState::Open {
3459 params,
3460 modify_state,
3461 reserved_state: None,
3462 } => (params, modify_state),
3463 _ => return Err(ChannelError::InvalidChannelState),
3464 };
3465
3466 if open_request.target_vp.is_none() {
3467 return Err(ChannelError::InterruptsDisabled);
3468 }
3469
3470 if let ModifyState::Modifying { pending_target_vp } = modify_state {
3471 if self.inner.state.check_version(Version::Iron) {
3472 tracelimit::warn_ratelimited!(
3475 key = %channel.offer.key(),
3476 "Client sent new ModifyChannel before receiving ModifyChannelResponse."
3477 );
3478 } else {
3479 *pending_target_vp = Some(request.target_vp);
3482 }
3483 } else {
3484 self.notifier.notify(
3485 offer_id,
3486 Action::Modify {
3487 target_vp: request.target_vp,
3488 },
3489 );
3490
3491 open_request.target_vp = Some(request.target_vp);
3493 *modify_state = ModifyState::Modifying {
3494 pending_target_vp: None,
3495 };
3496 }
3497
3498 Ok(())
3499 }
3500
3501 pub fn modify_channel_complete(&mut self, offer_id: OfferId, status: i32) {
3508 let channel = &mut self.inner.channels[offer_id];
3509
3510 if let ChannelState::Open {
3511 params,
3512 modify_state: ModifyState::Modifying { pending_target_vp },
3513 reserved_state: None,
3514 } = channel.state
3515 {
3516 channel.state = ChannelState::Open {
3517 params,
3518 modify_state: ModifyState::NotModifying,
3519 reserved_state: None,
3520 };
3521
3522 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
3524 let key = channel.offer.key();
3525 self.send_modify_channel_response(channel_id, status);
3526
3527 if let Some(target_vp) = pending_target_vp {
3529 let request = protocol::ModifyChannel {
3530 channel_id,
3531 target_vp,
3532 };
3533
3534 if let Err(error) = self.handle_modify_channel(&request) {
3535 tracelimit::warn_ratelimited!(?error, %key, "Pending ModifyChannel request failed.")
3536 }
3537 }
3538 }
3539 }
3540
3541 fn send_modify_channel_response(&mut self, channel_id: ChannelId, status: i32) {
3542 if self.inner.state.check_version(Version::Iron) {
3543 self.sender()
3544 .send_message(&protocol::ModifyChannelResponse { channel_id, status });
3545 }
3546 }
3547
3548 fn handle_modify_connection(&mut self, request: protocol::ModifyConnection) {
3549 if let Err(err) = self.modify_connection(request) {
3550 tracelimit::error_ratelimited!(?err, "modifying connection failed");
3551 self.complete_modify_connection(ModifyConnectionResponse::Modified(
3552 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
3553 ));
3554 }
3555 }
3556
3557 fn modify_connection(&mut self, request: protocol::ModifyConnection) -> anyhow::Result<()> {
3558 let ConnectionState::Connected(info) = &mut self.inner.state else {
3559 anyhow::bail!(
3560 "Invalid state for ModifyConnection request: {:?}",
3561 self.inner.state
3562 );
3563 };
3564
3565 if info.modifying {
3566 anyhow::bail!(
3567 "Duplicate ModifyConnection request, state: {:?}",
3568 self.inner.state
3569 );
3570 }
3571
3572 if matches!(
3573 info.monitor_page,
3574 Some(MonitorPageGpaInfo {
3575 server_allocated: true,
3576 ..
3577 })
3578 ) {
3579 anyhow::bail!("Cannot modify server-allocated monitor pages");
3580 }
3581
3582 if (request.child_to_parent_monitor_page_gpa == 0)
3583 != (request.parent_to_child_monitor_page_gpa == 0)
3584 {
3585 anyhow::bail!("Guest must specify either both or no monitor pages, {request:?}");
3586 }
3587
3588 let monitor_page = (request.child_to_parent_monitor_page_gpa != 0).then_some(
3589 MonitorPageGpaInfo::from_guest_gpas(MonitorPageGpas {
3590 child_to_parent: request.child_to_parent_monitor_page_gpa,
3591 parent_to_child: request.parent_to_child_monitor_page_gpa,
3592 }),
3593 );
3594
3595 info.modifying = true;
3596 info.monitor_page = monitor_page;
3597 tracing::debug!("modifying connection parameters.");
3598 self.notifier.modify_connection(request.into())?;
3599
3600 Ok(())
3601 }
3602
3603 pub fn complete_modify_connection(&mut self, response: ModifyConnectionResponse) {
3604 tracing::debug!(?response, "modifying connection parameters complete");
3605
3606 match &mut self.inner.state {
3610 ConnectionState::Connecting { .. } => self.complete_initiate_contact(response),
3611 ConnectionState::Disconnecting { .. } => self.complete_disconnect(),
3612 ConnectionState::Connected(info) => {
3613 let ModifyConnectionResponse::Modified(connection_state) = response else {
3614 panic!(
3615 "Relay should not return {:?} for a modify request with no version.",
3616 response
3617 );
3618 };
3619
3620 if !info.modifying {
3621 panic!(
3622 "ModifyConnection response while not modifying, state: {:?}",
3623 self.inner.state
3624 );
3625 }
3626
3627 info.modifying = false;
3628 self.sender()
3629 .send_message(&protocol::ModifyConnectionResponse { connection_state });
3630 }
3631 _ => panic!(
3632 "Invalid state for ModifyConnection response: {:?}",
3633 self.inner.state
3634 ),
3635 }
3636 }
3637
3638 fn handle_pause(&mut self) {
3639 tracelimit::info_ratelimited!("pausing sending messages");
3640 self.sender().send_message(&protocol::PauseResponse {});
3641 let ConnectionState::Connected(info) = &mut self.inner.state else {
3642 unreachable!(
3643 "in unexpected state {:?}, should be prevented by Message::parse()",
3644 self.inner.state
3645 );
3646 };
3647 info.paused = true;
3648 }
3649
3650 pub fn handle_synic_message(&mut self, message: SynicMessage) -> Result<(), ChannelError> {
3652 assert!(!self.is_resetting());
3653
3654 let version = self.inner.state.get_version();
3655 let msg = Message::parse(&message.data, version)?;
3656 tracing::trace!(?msg, message.trusted, "received vmbus message");
3657 if self.inner.state.is_trusted() && !message.trusted {
3662 tracelimit::warn_ratelimited!(?msg, "Received untrusted message");
3663 return Err(ChannelError::UntrustedMessage);
3664 }
3665
3666 match &mut self.inner.state {
3668 ConnectionState::Connected(info) if info.paused => {
3669 if !matches!(
3670 msg,
3671 Message::Resume(..)
3672 | Message::Unload(..)
3673 | Message::InitiateContact { .. }
3674 | Message::InitiateContact2 { .. }
3675 ) {
3676 tracelimit::warn_ratelimited!(?msg, "Received message while paused");
3677 return Err(ChannelError::Paused);
3678 }
3679 tracelimit::info_ratelimited!("resuming sending messages");
3680 info.paused = false;
3681 }
3682 _ => {}
3683 }
3684
3685 match msg {
3686 Message::InitiateContact2(input, ..) => {
3687 self.handle_initiate_contact(&input, &message, true)?
3688 }
3689 Message::InitiateContact(input, ..) => {
3690 self.handle_initiate_contact(&input.into(), &message, false)?
3691 }
3692 Message::Unload(..) => self.handle_unload(),
3693 Message::RequestOffers(..) => self.handle_request_offers()?,
3694 Message::GpadlHeader(input, range) => self.handle_gpadl_header(&input, range),
3695 Message::GpadlBody(input, range) => self.handle_gpadl_body(&input, range)?,
3696 Message::GpadlTeardown(input, ..) => self.handle_gpadl_teardown(&input)?,
3697 Message::OpenChannel(input, ..) => self.handle_open_channel(&input.into())?,
3698 Message::OpenChannel2(input, ..) => self.handle_open_channel(&input)?,
3699 Message::CloseChannel(input, ..) => self.handle_close_channel(&input)?,
3700 Message::RelIdReleased(input, ..) => self.handle_rel_id_released(&input)?,
3701 Message::TlConnectRequest(input, ..) => self.handle_tl_connect_request(input.into()),
3702 Message::TlConnectRequest2(input, ..) => self.handle_tl_connect_request(input),
3703 Message::ModifyChannel(input, ..) => self.handle_modify_channel(&input)?,
3704 Message::ModifyConnection(input, ..) => self.handle_modify_connection(input),
3705 Message::OpenReservedChannel(input, ..) => self.handle_open_reserved_channel(
3706 &input,
3707 version.expect("version validated by Message::parse"),
3708 )?,
3709 Message::CloseReservedChannel(input, ..) => {
3710 self.handle_close_reserved_channel(&input)?
3711 }
3712 Message::Pause(protocol::Pause, ..) => self.handle_pause(),
3713 Message::Resume(protocol::Resume, ..) => {}
3714 Message::OfferChannel(..)
3716 | Message::RescindChannelOffer(..)
3717 | Message::AllOffersDelivered(..)
3718 | Message::OpenResult(..)
3719 | Message::GpadlCreated(..)
3720 | Message::GpadlTorndown(..)
3721 | Message::VersionResponse(..)
3722 | Message::VersionResponse2(..)
3723 | Message::VersionResponse3(..)
3724 | Message::UnloadComplete(..)
3725 | Message::CloseReservedChannelResponse(..)
3726 | Message::TlConnectResult(..)
3727 | Message::ModifyChannelResponse(..)
3728 | Message::ModifyConnectionResponse(..)
3729 | Message::PauseResponse(..) => {
3730 unreachable!("Server received client message {:?}", msg);
3731 }
3732 }
3733 Ok(())
3734 }
3735
3736 pub fn gpadl_create_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId, status: i32) {
3738 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3739 tracelimit::error_ratelimited!(
3740 ?offer_id,
3741 key = %self.inner.channels[offer_id].offer.key(),
3742 ?gpadl_id,
3743 "invalid gpadl ID for channel"
3744 );
3745 return;
3746 };
3747 let retain = match gpadl.state {
3748 GpadlState::InProgress | GpadlState::TearingDown | GpadlState::Accepted => {
3749 tracelimit::error_ratelimited!(?offer_id, ?gpadl_id, ?gpadl, "invalid gpadl state");
3750 return;
3751 }
3752 GpadlState::Offered => {
3753 let channel_id = self.inner.channels[offer_id]
3754 .info
3755 .as_ref()
3756 .expect("assigned")
3757 .channel_id;
3758 self.inner
3759 .pending_messages
3760 .sender(self.notifier, self.inner.state.is_paused())
3761 .send_gpadl_created(channel_id, gpadl_id, status);
3762 if status >= 0 {
3763 gpadl.state = GpadlState::Accepted;
3764 true
3765 } else {
3766 false
3767 }
3768 }
3769 GpadlState::OfferedTearingDown => {
3770 if status >= 0 {
3771 self.notifier.notify(
3773 offer_id,
3774 Action::TeardownGpadl {
3775 gpadl_id,
3776 post_restore: false,
3777 },
3778 );
3779 gpadl.state = GpadlState::TearingDown;
3780 true
3781 } else {
3782 false
3783 }
3784 }
3785 };
3786 if !retain {
3787 self.inner
3788 .gpadls
3789 .remove(&(gpadl_id, offer_id))
3790 .expect("gpadl validated above");
3791
3792 self.check_disconnected();
3793 }
3794 }
3795
3796 pub fn gpadl_teardown_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId) {
3798 let channel = &mut self.inner.channels[offer_id];
3799 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3800 tracelimit::error_ratelimited!(
3801 ?offer_id,
3802 key = %channel.offer.key(),
3803 ?gpadl_id,
3804 "invalid gpadl ID for channel"
3805 );
3806 return;
3807 };
3808 tracing::debug!(
3809 offer_id = offer_id.0,
3810 key = %channel.offer.key(),
3811 gpadl_id = gpadl_id.0,
3812 "Gpadl teardown complete"
3813 );
3814 match gpadl.state {
3815 GpadlState::InProgress
3816 | GpadlState::Offered
3817 | GpadlState::OfferedTearingDown
3818 | GpadlState::Accepted => {
3819 tracelimit::error_ratelimited!(?offer_id, key = %channel.offer.key(), ?gpadl_id, ?gpadl, "invalid gpadl state");
3820 }
3821 GpadlState::TearingDown => {
3822 if !channel.state.is_released() {
3823 self.sender().send_gpadl_torndown(gpadl_id);
3824 }
3825 self.inner
3826 .gpadls
3827 .remove(&(gpadl_id, offer_id))
3828 .expect("gpadl validated above");
3829
3830 self.check_disconnected();
3831 }
3832 }
3833 }
3834
3835 fn sender(&mut self) -> MessageSender<'_, N> {
3840 self.inner
3841 .pending_messages
3842 .sender(self.notifier, self.inner.state.is_paused())
3843 }
3844}
3845
3846fn revoke<N: Notifier>(
3847 mut sender: MessageSender<'_, N>,
3848 offer_id: OfferId,
3849 channel: &mut Channel,
3850 gpadls: &mut GpadlMap,
3851) -> bool {
3852 let info = match channel.state {
3853 ChannelState::Closed
3854 | ChannelState::Open { .. }
3855 | ChannelState::Opening { .. }
3856 | ChannelState::Closing { .. }
3857 | ChannelState::ClosingReopen { .. } => {
3858 channel.state = ChannelState::Revoked;
3859 Some(channel.info.as_ref().expect("assigned"))
3860 }
3861 ChannelState::Reoffered => {
3862 channel.state = ChannelState::Revoked;
3863 None
3864 }
3865 ChannelState::ClientReleased
3866 | ChannelState::OpeningClientRelease
3867 | ChannelState::ClosingClientRelease => None,
3868 ChannelState::Revoked => return true,
3870 };
3871 let retain = !channel.state.is_released();
3872
3873 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3875 if gpadl_offer_id != offer_id {
3876 return true;
3877 }
3878
3879 match gpadl.state {
3880 GpadlState::InProgress => true,
3881 GpadlState::Offered => {
3882 if let Some(info) = info {
3883 sender.send_gpadl_created(
3884 info.channel_id,
3885 gpadl_id,
3886 protocol::STATUS_UNSUCCESSFUL,
3887 );
3888 }
3889 false
3890 }
3891 GpadlState::OfferedTearingDown => false,
3892 GpadlState::Accepted => true,
3893 GpadlState::TearingDown => {
3894 if info.is_some() {
3895 sender.send_gpadl_torndown(gpadl_id);
3896 }
3897 false
3898 }
3899 }
3900 });
3901 if let Some(info) = info {
3902 sender.send_rescind(info);
3903 }
3904 if channel.restore_state != RestoreState::New {
3906 channel.restore_state = RestoreState::Restored;
3907 }
3908 retain
3909}
3910
3911struct PendingMessages(VecDeque<OutgoingMessage>);
3912
3913impl PendingMessages {
3914 fn sender<'a, N: Notifier>(
3916 &'a mut self,
3917 notifier: &'a mut N,
3918 is_paused: bool,
3919 ) -> MessageSender<'a, N> {
3920 MessageSender {
3921 notifier,
3922 pending_messages: self,
3923 is_paused,
3924 }
3925 }
3926}
3927
3928struct MessageSender<'a, N> {
3931 notifier: &'a mut N,
3932 pending_messages: &'a mut PendingMessages,
3933 is_paused: bool,
3934}
3935
3936impl<N: Notifier> MessageSender<'_, N> {
3937 fn send_message<
3939 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3940 >(
3941 &mut self,
3942 msg: &T,
3943 ) {
3944 let message = OutgoingMessage::new(msg);
3945
3946 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3947 if !self.pending_messages.0.is_empty()
3949 || self.is_paused
3950 || !self.notifier.send_message(&message, MessageTarget::Default)
3951 {
3952 tracing::trace!("message queued");
3953 self.pending_messages.0.push_back(message);
3955 }
3956 }
3957
3958 fn send_message_with_target<
3960 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3961 >(
3962 &mut self,
3963 msg: &T,
3964 target: MessageTarget,
3965 ) {
3966 if target == MessageTarget::Default {
3967 self.send_message(msg);
3968 } else {
3969 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3970 let message = OutgoingMessage::new(msg);
3973 if !self.notifier.send_message(&message, target) {
3974 tracelimit::warn_ratelimited!(?target, "failed to send message");
3975 }
3976 }
3977 }
3978
3979 fn send_offer(&mut self, channel: &mut Channel, connection_info: &ConnectionInfo) {
3981 let info = channel.info.as_ref().expect("assigned");
3982 let mut flags = channel.offer.flags;
3983
3984 if !connection_info
3986 .version
3987 .feature_flags
3988 .confidential_channels()
3989 {
3990 flags.set_confidential_ring_buffer(false);
3991 flags.set_confidential_external_memory(false);
3992 }
3993
3994 if !connection_info.version.feature_flags.gpa_pinning() {
3995 flags.set_require_pinned_external_memory(false);
3996 }
3997
3998 let monitor_id = connection_info.monitor_page.and(info.monitor_id);
4005 let msg = protocol::OfferChannel {
4006 interface_id: channel.offer.interface_id,
4007 instance_id: channel.offer.instance_id,
4008 rsvd: [0; 4],
4009 flags,
4010 mmio_megabytes: channel.offer.mmio_megabytes,
4011 user_defined: channel.offer.user_defined,
4012 subchannel_index: channel.offer.subchannel_index,
4013 mmio_megabytes_optional: channel.offer.mmio_megabytes_optional,
4014 channel_id: info.channel_id,
4015 monitor_id: monitor_id.unwrap_or(MonitorId::INVALID).0,
4016 monitor_allocated: monitor_id.is_some().into(),
4017 is_dedicated: 1,
4020 connection_id: info.connection_id,
4021 };
4022 tracing::info!(
4023 channel_id = msg.channel_id.0,
4024 connection_id = msg.connection_id,
4025 offer_order = ?channel.offer.offer_order,
4026 key = %channel.offer.key(),
4027 "sending offer to guest"
4028 );
4029
4030 self.send_message(&msg);
4031 }
4032
4033 fn send_open_result(
4034 &mut self,
4035 channel_id: ChannelId,
4036 open_request: &OpenRequest,
4037 result: i32,
4038 target: MessageTarget,
4039 ) {
4040 self.send_message_with_target(
4041 &protocol::OpenResult {
4042 channel_id,
4043 open_id: open_request.open_id,
4044 status: result as u32,
4045 },
4046 target,
4047 );
4048 }
4049
4050 fn send_gpadl_created(&mut self, channel_id: ChannelId, gpadl_id: GpadlId, status: i32) {
4051 self.send_message(&protocol::GpadlCreated {
4052 channel_id,
4053 gpadl_id,
4054 status,
4055 });
4056 }
4057
4058 fn send_gpadl_torndown(&mut self, gpadl_id: GpadlId) {
4059 self.send_message(&protocol::GpadlTorndown { gpadl_id });
4060 }
4061
4062 fn send_rescind(&mut self, info: &OfferedInfo) {
4063 tracing::info!(
4064 channel_id = info.channel_id.0,
4065 "rescinding channel from guest"
4066 );
4067
4068 self.send_message(&protocol::RescindChannelOffer {
4069 channel_id: info.channel_id,
4070 });
4071 }
4072}
4073
4074struct VersionResponseData {
4076 version: VersionInfo,
4077 state: protocol::ConnectionState,
4078 monitor_pages: Option<MonitorPageGpas>,
4079}
4080
4081impl VersionResponseData {
4082 fn new(version: VersionInfo, state: protocol::ConnectionState) -> Self {
4084 VersionResponseData {
4085 version,
4086 state,
4087 monitor_pages: None,
4088 }
4089 }
4090
4091 fn with_monitor_pages(mut self, monitor_pages: Option<MonitorPageGpas>) -> Self {
4093 self.monitor_pages = monitor_pages;
4094 self
4095 }
4096}