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