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(
1087 &mut self,
1088 assigned_channels: &AssignedChannels,
1089 channel_id: ChannelId,
1090 ) -> Result<(OfferId, &mut Channel), ChannelError> {
1091 let offer_id = assigned_channels
1092 .get(channel_id)
1093 .ok_or(ChannelError::UnknownChannelId)?;
1094 let channel = &mut self[offer_id];
1095 if channel.state.is_released() {
1096 return Err(ChannelError::ChannelReleased);
1097 }
1098 assert_eq!(
1099 channel.info.as_ref().map(|info| info.channel_id),
1100 Some(channel_id)
1101 );
1102 Ok((offer_id, channel))
1103 }
1104
1105 fn get_by_channel_id(
1107 &self,
1108 assigned_channels: &AssignedChannels,
1109 channel_id: ChannelId,
1110 ) -> Result<(OfferId, &Channel), ChannelError> {
1111 let offer_id = assigned_channels
1112 .get(channel_id)
1113 .ok_or(ChannelError::UnknownChannelId)?;
1114 let channel = &self[offer_id];
1115 if channel.state.is_released() {
1116 return Err(ChannelError::ChannelReleased);
1117 }
1118 assert_eq!(
1119 channel.info.as_ref().map(|info| info.channel_id),
1120 Some(channel_id)
1121 );
1122 Ok((offer_id, channel))
1123 }
1124
1125 fn get_by_key_mut(&mut self, key: &OfferKey) -> Option<(OfferId, &mut Channel)> {
1128 for (offer_id, channel) in self.iter_mut() {
1129 if channel.offer.instance_id == key.instance_id
1130 && channel.offer.interface_id == key.interface_id
1131 && channel.offer.subchannel_index == key.subchannel_index
1132 {
1133 return Some((offer_id, channel));
1134 }
1135 }
1136 None
1137 }
1138
1139 fn iter(&self) -> impl Iterator<Item = (OfferId, &Channel)> {
1141 self.channels
1142 .iter()
1143 .map(|(id, channel)| (OfferId(id), channel))
1144 }
1145
1146 fn iter_mut(&mut self) -> impl Iterator<Item = (OfferId, &mut Channel)> {
1148 self.channels
1149 .iter_mut()
1150 .map(|(id, channel)| (OfferId(id), channel))
1151 }
1152
1153 fn retain<F>(&mut self, mut f: F)
1155 where
1156 F: FnMut(OfferId, &mut Channel) -> bool,
1157 {
1158 self.channels.retain(|id, channel| {
1159 let retain = f(OfferId(id), channel);
1160 if !retain {
1161 assert!(channel.info.is_none());
1162 }
1163 retain
1164 })
1165 }
1166}
1167
1168impl Index<OfferId> for ChannelList {
1169 type Output = Channel;
1170
1171 fn index(&self, offer_id: OfferId) -> &Self::Output {
1172 &self.channels[offer_id.0]
1173 }
1174}
1175
1176impl IndexMut<OfferId> for ChannelList {
1177 fn index_mut(&mut self, offer_id: OfferId) -> &mut Self::Output {
1178 &mut self.channels[offer_id.0]
1179 }
1180}
1181
1182#[derive(Debug, Inspect)]
1184struct Gpadl {
1185 count: u16,
1186 #[inspect(skip)]
1187 buf: Vec<u64>,
1188 state: GpadlState,
1189}
1190
1191#[derive(Debug, Copy, Clone, PartialEq, Eq, Inspect)]
1192enum GpadlState {
1193 InProgress,
1195 Offered,
1197 OfferedTearingDown,
1200 Accepted,
1202 TearingDown,
1204}
1205
1206impl Gpadl {
1207 fn new(count: u16, len: usize) -> Self {
1210 Self {
1211 state: GpadlState::InProgress,
1212 count,
1213 buf: Vec::with_capacity(len),
1214 }
1215 }
1216
1217 fn append(&mut self, data: &[u8]) -> Result<bool, ChannelError> {
1219 if self.state == GpadlState::InProgress {
1220 let buf = &mut self.buf;
1221 let len = min(data.len() & !7, (buf.capacity() - buf.len()) * 8);
1226 let data = &data[..len];
1227 let start = buf.len();
1228 buf.resize(buf.len() + data.len() / 8, 0);
1229 buf[start..].as_mut_bytes().copy_from_slice(data);
1230 Ok(if buf.len() == buf.capacity() {
1231 gparange::validate_gpa_ranges(self.count as usize, buf)
1232 .map_err(ChannelError::InvalidGpaRange)?;
1233 self.state = GpadlState::Offered;
1234 true
1235 } else {
1236 false
1237 })
1238 } else {
1239 Err(ChannelError::GpadlAlreadyComplete)
1240 }
1241 }
1242}
1243
1244#[derive(Debug, Copy, Clone)]
1246pub struct OpenParams {
1247 pub open_data: OpenData,
1248 pub connection_id: u32,
1249 pub event_flag: u16,
1250 pub monitor_info: Option<MonitorInfo>,
1251 pub flags: protocol::OpenChannelFlags,
1252 pub reserved_target: Option<ConnectionTarget>,
1253 pub channel_id: ChannelId,
1254}
1255
1256impl OpenParams {
1257 fn from_request(
1258 info: &OfferedInfo,
1259 request: &OpenRequest,
1260 monitor_info: Option<MonitorInfo>,
1261 reserved_target: Option<ConnectionTarget>,
1262 ) -> Self {
1263 let (event_flag, connection_id) = if let Some(id) = request.guest_specified_interrupt_info {
1266 (id.event_flag, id.connection_id)
1267 } else {
1268 (info.channel_id.0 as u16, info.connection_id)
1269 };
1270
1271 Self {
1272 open_data: OpenData {
1273 target_vp: request.target_vp,
1274 ring_offset: request.downstream_ring_buffer_page_offset,
1275 ring_gpadl_id: request.ring_buffer_gpadl_id,
1276 user_data: request.user_data,
1277 event_flag,
1278 connection_id,
1279 },
1280 connection_id,
1281 event_flag,
1282 monitor_info: request.target_vp.and(monitor_info),
1284 flags: request.flags.with_unused(0),
1285 reserved_target,
1286 channel_id: info.channel_id,
1287 }
1288 }
1289}
1290
1291#[derive(Debug)]
1293pub enum Action {
1294 Open(OpenParams, VersionInfo),
1295 Close,
1296 Gpadl(GpadlId, u16, Vec<u64>),
1297 TeardownGpadl {
1298 gpadl_id: GpadlId,
1299 post_restore: bool,
1300 },
1301 Modify {
1302 target_vp: u32,
1303 },
1304}
1305
1306static SUPPORTED_VERSIONS: &[Version] = &[
1308 Version::V1,
1309 Version::Win7,
1310 Version::Win8,
1311 Version::Win8_1,
1312 Version::Win10,
1313 Version::Win10Rs3_0,
1314 Version::Win10Rs3_1,
1315 Version::Win10Rs4,
1316 Version::Win10Rs5,
1317 Version::Iron,
1318 Version::Copper,
1319];
1320
1321const SUPPORTED_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
1324 .with_guest_specified_signal_parameters(true)
1325 .with_channel_interrupt_redirection(true)
1326 .with_modify_connection(true)
1327 .with_client_id(true)
1328 .with_pause_resume(true)
1329 .with_server_specified_monitor_pages(true);
1330
1331pub trait Notifier: Send {
1333 fn notify(&mut self, offer_id: OfferId, action: Action);
1335
1336 fn forward_unhandled(&mut self, request: InitiateContactRequest);
1338
1339 fn modify_connection(&mut self, request: ModifyConnectionRequest) -> anyhow::Result<()>;
1345
1346 fn inspect(&self, version: Option<VersionInfo>, offer_id: OfferId, req: inspect::Request<'_>) {
1348 let _ = (version, offer_id, req);
1349 }
1350
1351 #[must_use]
1354 fn send_message(&mut self, message: &OutgoingMessage, target: MessageTarget) -> bool;
1355
1356 fn notify_hvsock(&mut self, request: &HvsockConnectRequest);
1358
1359 fn reset_complete(&mut self);
1361
1362 fn unload_complete(&mut self);
1364}
1365
1366impl Server {
1367 pub fn new(
1369 vtl: Vtl,
1370 child_connection_id: u32,
1371 channel_id_offset: u16,
1372 use_absolute_channel_order: bool,
1373 ) -> Self {
1374 Server {
1375 state: ConnectionState::Disconnected,
1376 channels: ChannelList::new(),
1377 assigned_channels: AssignedChannels::new(vtl, channel_id_offset),
1378 assigned_monitors: AssignedMonitors::new(),
1379 gpadls: Default::default(),
1380 incomplete_gpadls: Default::default(),
1381 child_connection_id,
1382 max_version: None,
1383 delayed_max_version: None,
1384 max_restore_version: None,
1385 pending_messages: PendingMessages(VecDeque::new()),
1386 require_server_allocated_mnf: false,
1387 use_absolute_channel_order,
1388 }
1389 }
1390
1391 pub fn with_notifier<'a, T: Notifier>(
1393 &'a mut self,
1394 notifier: &'a mut T,
1395 ) -> ServerWithNotifier<'a, T> {
1396 self.validate();
1397 ServerWithNotifier {
1398 inner: self,
1399 notifier,
1400 }
1401 }
1402
1403 pub fn set_require_server_allocated_mnf(&mut self, require: bool) {
1406 self.require_server_allocated_mnf = require;
1407 }
1408
1409 fn validate(&self) {
1410 #[cfg(debug_assertions)]
1411 for (_, channel) in self.channels.iter() {
1412 let should_have_info = !channel.state.is_released();
1413 if channel.info.is_some() != should_have_info {
1414 panic!("channel invariant violation: {channel:?}");
1415 }
1416 }
1417 }
1418
1419 pub fn set_compatibility_version(&mut self, version: MaxVersionInfo, delay: bool) {
1424 if delay {
1425 self.delayed_max_version = Some(version)
1426 } else {
1427 tracing::info!(?version, "Limiting VmBus connections to version");
1428 self.max_version = Some(version);
1429 }
1430 }
1431
1432 pub fn set_restore_compatibility_version(&mut self, version: MaxVersionInfo) {
1440 tracing::info!(?version, "Limiting VmBus restore to version");
1441 self.max_restore_version = Some(version);
1442 }
1443
1444 pub fn channel_gpadls(&self, offer_id: OfferId) -> Vec<RestoredGpadl> {
1445 self.gpadls
1446 .iter()
1447 .filter_map(|(&(gpadl_id, gpadl_offer_id), gpadl)| {
1448 if offer_id != gpadl_offer_id {
1449 return None;
1450 }
1451 let accepted = match gpadl.state {
1452 GpadlState::Offered | GpadlState::OfferedTearingDown => false,
1453 GpadlState::Accepted => true,
1454 GpadlState::InProgress | GpadlState::TearingDown => return None,
1455 };
1456 Some(RestoredGpadl {
1457 request: GpadlRequest {
1458 id: gpadl_id,
1459 count: gpadl.count,
1460 buf: gpadl.buf.clone(),
1461 },
1462 accepted,
1463 })
1464 })
1465 .collect()
1466 }
1467
1468 pub fn get_version(&self) -> Option<VersionInfo> {
1469 self.state.get_version()
1470 }
1471
1472 pub fn get_restore_open_params(&self, offer_id: OfferId) -> Result<OpenParams, RestoreError> {
1473 let channel = &self.channels[offer_id];
1474
1475 match channel.restore_state {
1477 RestoreState::New => {
1478 return Err(RestoreError::MissingChannel(channel.offer.key()));
1482 }
1483 RestoreState::Restoring => {}
1484 RestoreState::Unmatched => unreachable!(),
1485 RestoreState::Restored => {
1486 return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1487 }
1488 }
1489
1490 let info = channel
1491 .info
1492 .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1493
1494 let (request, reserved_state) = match channel.state {
1495 ChannelState::Closed => {
1496 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1497 }
1498 ChannelState::Closing { params, .. } | ChannelState::ClosingReopen { params, .. } => {
1499 (params, None)
1500 }
1501 ChannelState::Opening {
1502 request,
1503 reserved_state,
1504 } => (request, reserved_state),
1505 ChannelState::Open {
1506 params,
1507 reserved_state,
1508 ..
1509 } => (params, reserved_state),
1510 ChannelState::ClientReleased | ChannelState::Reoffered => {
1511 return Err(RestoreError::MissingChannel(channel.offer.key()));
1512 }
1513 ChannelState::Revoked
1514 | ChannelState::ClosingClientRelease
1515 | ChannelState::OpeningClientRelease => unreachable!(),
1516 };
1517
1518 Ok(OpenParams::from_request(
1519 &info,
1520 &request,
1521 channel.handled_monitor_info(),
1522 reserved_state.map(|state| state.target),
1523 ))
1524 }
1525
1526 pub fn has_pending_messages(&self) -> bool {
1528 !self.pending_messages.0.is_empty() && !self.state.is_paused()
1529 }
1530
1531 pub fn poll_flush_pending_messages(
1533 &mut self,
1534 mut send: impl FnMut(&OutgoingMessage) -> Poll<()>,
1535 ) -> Poll<()> {
1536 if !self.state.is_paused() {
1537 while let Some(message) = self.pending_messages.0.front() {
1538 ready!(send(message));
1539 self.pending_messages.0.pop_front();
1540 }
1541 }
1542
1543 Poll::Ready(())
1544 }
1545}
1546
1547impl<'a, N: 'a + Notifier> ServerWithNotifier<'a, N> {
1548 pub fn restore_channel(&mut self, offer_id: OfferId, open: bool) -> Result<(), RestoreError> {
1554 let channel = &mut self.inner.channels[offer_id];
1555
1556 match channel.restore_state {
1559 RestoreState::New => {
1560 if open {
1564 return Err(RestoreError::MissingChannel(channel.offer.key()));
1565 } else {
1566 return Ok(());
1567 }
1568 }
1569 RestoreState::Restoring => {}
1570 RestoreState::Unmatched => unreachable!(),
1571 RestoreState::Restored => {
1572 return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1573 }
1574 }
1575
1576 let info = channel
1577 .info
1578 .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1579
1580 if let Some(monitor_info) = channel.handled_monitor_info() {
1581 if !self
1582 .inner
1583 .assigned_monitors
1584 .claim_monitor(monitor_info.monitor_id)
1585 {
1586 return Err(RestoreError::DuplicateMonitorId(monitor_info.monitor_id.0));
1587 }
1588 }
1589
1590 if open {
1591 match channel.state {
1592 ChannelState::Closed => {
1593 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1594 }
1595 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
1596 self.notifier.notify(offer_id, Action::Close);
1597 }
1598 ChannelState::Opening {
1599 request,
1600 reserved_state,
1601 } => {
1602 self.inner
1603 .pending_messages
1604 .sender(self.notifier, self.inner.state.is_paused())
1605 .send_open_result(
1606 info.channel_id,
1607 &request,
1608 protocol::STATUS_SUCCESS,
1609 MessageTarget::for_offer(offer_id, &reserved_state),
1610 );
1611 channel.state = ChannelState::Open {
1612 params: request,
1613 modify_state: ModifyState::NotModifying,
1614 reserved_state,
1615 };
1616 }
1617 ChannelState::Open { .. } => {}
1618 ChannelState::ClientReleased | ChannelState::Reoffered => {
1619 return Err(RestoreError::MissingChannel(channel.offer.key()));
1620 }
1621 ChannelState::Revoked
1622 | ChannelState::ClosingClientRelease
1623 | ChannelState::OpeningClientRelease => unreachable!(),
1624 };
1625 } else {
1626 match channel.state {
1627 ChannelState::Closed => {}
1628 ChannelState::Reoffered => {}
1633 ChannelState::Closing { .. } => {
1634 channel.state = ChannelState::Closed;
1635 }
1636 ChannelState::ClosingReopen { request, .. } => {
1637 self.notifier.notify(
1638 offer_id,
1639 Action::Open(
1640 OpenParams::from_request(
1641 &info,
1642 &request,
1643 channel.handled_monitor_info(),
1644 None,
1645 ),
1646 self.inner.state.get_version().expect("must be connected"),
1647 ),
1648 );
1649 channel.state = ChannelState::Opening {
1650 request,
1651 reserved_state: None,
1652 };
1653 }
1654 ChannelState::Opening {
1655 request,
1656 reserved_state,
1657 } => {
1658 self.notifier.notify(
1659 offer_id,
1660 Action::Open(
1661 OpenParams::from_request(
1662 &info,
1663 &request,
1664 channel.handled_monitor_info(),
1665 reserved_state.map(|state| state.target),
1666 ),
1667 self.inner.state.get_version().expect("must be connected"),
1668 ),
1669 );
1670 }
1671 ChannelState::Open { .. } => {
1672 return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1673 }
1674 ChannelState::ClientReleased => {
1675 return Err(RestoreError::MissingChannel(channel.offer.key()));
1676 }
1677 ChannelState::Revoked
1678 | ChannelState::ClosingClientRelease
1679 | ChannelState::OpeningClientRelease => unreachable!(),
1680 }
1681 }
1682
1683 channel.restore_state = RestoreState::Restored;
1684 Ok(())
1685 }
1686
1687 pub fn revoke_unclaimed_channels(&mut self) {
1690 for (offer_id, channel) in self.inner.channels.iter_mut() {
1691 match channel.restore_state {
1692 RestoreState::Restored => {
1693 }
1695 RestoreState::New => {
1696 if let ConnectionState::Connected(info) = &self.inner.state {
1701 if info.offers_sent && matches!(channel.state, ChannelState::ClientReleased)
1702 {
1703 channel.prepare_channel(
1704 offer_id,
1705 &mut self.inner.assigned_channels,
1706 &mut self.inner.assigned_monitors,
1707 );
1708 channel.state = ChannelState::Closed;
1709 self.inner
1710 .pending_messages
1711 .sender(self.notifier, self.inner.state.is_paused())
1712 .send_offer(channel, info);
1713 }
1714 }
1715 }
1716 RestoreState::Restoring => {
1717 let retain = revoke(
1721 self.inner
1722 .pending_messages
1723 .sender(self.notifier, self.inner.state.is_paused()),
1724 offer_id,
1725 channel,
1726 &mut self.inner.gpadls,
1727 );
1728 assert!(retain, "channel has not been released");
1729 channel.state = ChannelState::Reoffered;
1730 }
1731 RestoreState::Unmatched => {
1732 let retain = revoke(
1735 self.inner
1736 .pending_messages
1737 .sender(self.notifier, self.inner.state.is_paused()),
1738 offer_id,
1739 channel,
1740 &mut self.inner.gpadls,
1741 );
1742 assert!(retain, "channel has not been released");
1743 }
1744 }
1745 }
1746
1747 for (&(gpadl_id, offer_id), gpadl) in self.inner.gpadls.iter_mut() {
1749 match gpadl.state {
1750 GpadlState::InProgress | GpadlState::Accepted => {}
1751 GpadlState::Offered => {
1752 self.notifier.notify(
1753 offer_id,
1754 Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
1755 );
1756 }
1757 GpadlState::TearingDown => {
1758 self.notifier.notify(
1759 offer_id,
1760 Action::TeardownGpadl {
1761 gpadl_id,
1762 post_restore: true,
1763 },
1764 );
1765 }
1766 GpadlState::OfferedTearingDown => unreachable!(),
1767 }
1768 }
1769
1770 self.check_disconnected();
1771 }
1772
1773 pub fn reset(&mut self) {
1778 assert!(!self.is_resetting());
1779 if self.request_disconnect(ConnectionAction::Reset) {
1780 self.complete_reset();
1781 }
1782 }
1783
1784 fn complete_reset(&mut self) {
1785 for (_, channel) in self.inner.channels.iter_mut() {
1787 channel.restore_state = RestoreState::New;
1788 }
1789 self.inner.pending_messages.0.clear();
1790 self.notifier.reset_complete();
1791 }
1792
1793 pub fn offer_channel(&mut self, offer: OfferParamsInternal) -> Result<OfferId, OfferError> {
1795 if let Some((offer_id, channel)) = self.inner.channels.get_by_key_mut(&offer.key()) {
1797 if channel.restore_state != RestoreState::Unmatched
1801 && !matches!(channel.state, ChannelState::Revoked)
1802 {
1803 return Err(OfferError::AlreadyExists(offer.key()));
1804 }
1805
1806 let info = channel.info.expect("assigned");
1807 if channel.restore_state == RestoreState::Unmatched {
1808 tracing::debug!(
1809 offer_id = offer_id.0,
1810 key = %channel.offer.key(),
1811 "matched channel"
1812 );
1813
1814 assert!(!matches!(channel.state, ChannelState::Revoked));
1815 channel.restore_state = RestoreState::Restoring;
1819
1820 if let MnfUsage::Relayed { monitor_id } = offer.use_mnf {
1823 if info.monitor_id != Some(MonitorId(monitor_id)) {
1824 return Err(OfferError::MismatchedMonitorId(
1825 info.monitor_id,
1826 MonitorId(monitor_id),
1827 ));
1828 }
1829 }
1830 } else {
1831 channel.state = ChannelState::Reoffered;
1835 tracing::info!(?offer_id, key = %channel.offer.key(), "channel marked for reoffer");
1836 }
1837
1838 channel.offer = offer;
1839 return Ok(offer_id);
1840 }
1841
1842 let mut connected_info = None;
1843 let state = match &self.inner.state {
1844 ConnectionState::Connected(info) => {
1845 if info.offers_sent {
1846 connected_info = Some(info);
1847 ChannelState::Closed
1848 } else {
1849 ChannelState::ClientReleased
1850 }
1851 }
1852 ConnectionState::Connecting { .. }
1853 | ConnectionState::Disconnecting { .. }
1854 | ConnectionState::Disconnected => ChannelState::ClientReleased,
1855 };
1856
1857 if self.inner.channels.len() >= self.inner.assigned_channels.allowable_channel_count() {
1859 return Err(OfferError::TooManyChannels);
1860 }
1861
1862 let key = offer.key();
1863 let confidential_ring_buffer = offer.flags.confidential_ring_buffer();
1864 let confidential_external_memory = offer.flags.confidential_external_memory();
1865 let channel = Channel {
1866 info: None,
1867 offer,
1868 state,
1869 restore_state: RestoreState::New,
1870 };
1871
1872 let offer_id = self.inner.channels.offer(channel);
1873 if let Some(info) = connected_info {
1874 let channel = &mut self.inner.channels[offer_id];
1875 channel.prepare_channel(
1876 offer_id,
1877 &mut self.inner.assigned_channels,
1878 &mut self.inner.assigned_monitors,
1879 );
1880
1881 self.inner
1882 .pending_messages
1883 .sender(self.notifier, self.inner.state.is_paused())
1884 .send_offer(channel, info);
1885 }
1886
1887 tracing::info!(?offer_id, %key, confidential_ring_buffer, confidential_external_memory, "new channel");
1888 Ok(offer_id)
1889 }
1890
1891 pub fn revoke_channel(&mut self, offer_id: OfferId) {
1893 let channel = &mut self.inner.channels[offer_id];
1894 let retain = revoke(
1895 self.inner
1896 .pending_messages
1897 .sender(self.notifier, self.inner.state.is_paused()),
1898 offer_id,
1899 channel,
1900 &mut self.inner.gpadls,
1901 );
1902 if !retain {
1903 self.inner.channels.remove(offer_id);
1904 }
1905
1906 self.check_disconnected();
1907 }
1908
1909 pub fn open_complete(&mut self, offer_id: OfferId, result: i32) {
1911 let channel = &mut self.inner.channels[offer_id];
1912 tracing::debug!(offer_id = offer_id.0, key = %channel.offer.key(), result, "open complete");
1913
1914 match channel.state {
1915 ChannelState::Opening {
1916 request,
1917 reserved_state,
1918 } => {
1919 let channel_id = channel.info.expect("assigned").channel_id;
1920 if result >= 0 {
1921 tracelimit::info_ratelimited!(
1922 offer_id = offer_id.0,
1923 channel_id = channel_id.0,
1924 key = %channel.offer.key(),
1925 result,
1926 "opened channel"
1927 );
1928 } else {
1929 tracelimit::error_ratelimited!(
1931 offer_id = offer_id.0,
1932 channel_id = channel_id.0,
1933 key = %channel.offer.key(),
1934 result,
1935 "failed to open channel"
1936 );
1937 }
1938
1939 self.inner
1940 .pending_messages
1941 .sender(self.notifier, self.inner.state.is_paused())
1942 .send_open_result(
1943 channel_id,
1944 &request,
1945 result,
1946 MessageTarget::for_offer(offer_id, &reserved_state),
1947 );
1948 channel.state = if result >= 0 {
1949 ChannelState::Open {
1950 params: request,
1951 modify_state: ModifyState::NotModifying,
1952 reserved_state,
1953 }
1954 } else {
1955 ChannelState::Closed
1956 };
1957 }
1958 ChannelState::OpeningClientRelease => {
1959 tracing::info!(
1960 offer_id = offer_id.0,
1961 key = %channel.offer.key(),
1962 result,
1963 "opened channel (client released)"
1964 );
1965
1966 if result >= 0 {
1967 channel.state = ChannelState::ClosingClientRelease;
1968 self.notifier.notify(offer_id, Action::Close);
1969 } else {
1970 channel.state = ChannelState::ClientReleased;
1971 self.check_disconnected();
1972 }
1973 }
1974
1975 ChannelState::ClientReleased
1976 | ChannelState::Closed
1977 | ChannelState::Open { .. }
1978 | ChannelState::Closing { .. }
1979 | ChannelState::ClosingReopen { .. }
1980 | ChannelState::Revoked
1981 | ChannelState::Reoffered
1982 | ChannelState::ClosingClientRelease => {
1983 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid open complete")
1984 }
1985 }
1986 }
1987
1988 fn are_channels_reset(&self, include_reserved: bool) -> bool {
1991 self.inner.gpadls.keys().all(|(_, offer_id)| {
1992 !include_reserved && self.inner.channels[*offer_id].state.is_reserved()
1993 }) && self.inner.channels.iter().all(|(_, channel)| {
1994 matches!(channel.state, ChannelState::ClientReleased)
1995 || (!include_reserved && channel.state.is_reserved())
1996 })
1997 }
1998
1999 fn check_disconnected(&mut self) {
2003 match self.inner.state {
2004 ConnectionState::Disconnecting {
2005 next_action,
2006 modify_sent: false,
2007 } => {
2008 if self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)) {
2009 self.notify_disconnect(next_action);
2010 }
2011 }
2012 ConnectionState::Disconnecting {
2013 modify_sent: true, ..
2014 }
2015 | ConnectionState::Disconnected
2016 | ConnectionState::Connected { .. }
2017 | ConnectionState::Connecting { .. } => (),
2018 }
2019 }
2020
2021 fn notify_disconnect(&mut self, next_action: ConnectionAction) {
2023 debug_assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2025 self.inner.state = ConnectionState::Disconnecting {
2026 next_action,
2027 modify_sent: true,
2028 };
2029
2030 self.notifier
2032 .modify_connection(ModifyConnectionRequest {
2033 monitor_page: Update::Reset,
2034 interrupt_page: Update::Reset,
2035 ..Default::default()
2036 })
2037 .expect("resetting state should not fail");
2038 }
2039
2040 fn is_resetting(&self) -> bool {
2043 matches!(
2044 &self.inner.state,
2045 ConnectionState::Connecting {
2046 next_action: ConnectionAction::Reset,
2047 ..
2048 } | ConnectionState::Disconnecting {
2049 next_action: ConnectionAction::Reset,
2050 ..
2051 }
2052 )
2053 }
2054
2055 pub fn close_complete(&mut self, offer_id: OfferId) {
2057 let channel = &mut self.inner.channels[offer_id];
2058 tracing::info!(offer_id = offer_id.0, key = %channel.offer.key(), "closed channel");
2059 match channel.state {
2060 ChannelState::Closing {
2061 reserved_state: Some(reserved_state),
2062 ..
2063 } => {
2064 channel.state = ChannelState::Closed;
2065 let channel_id = channel.info.expect("assigned").channel_id;
2066 self.send_close_reserved_channel_response(
2070 channel_id,
2071 offer_id,
2072 reserved_state.target,
2073 );
2074
2075 if !matches!(self.inner.state, ConnectionState::Connected { .. }) {
2076 let channel = &mut self.inner.channels[offer_id];
2078 if Self::client_release_channel(
2081 self.inner
2082 .pending_messages
2083 .sender(self.notifier, self.inner.state.is_paused()),
2084 offer_id,
2085 channel,
2086 &mut self.inner.gpadls,
2087 &mut self.inner.incomplete_gpadls,
2088 &mut self.inner.assigned_channels,
2089 &mut self.inner.assigned_monitors,
2090 None,
2091 false,
2092 ) {
2093 self.inner.channels.remove(offer_id);
2094 }
2095 }
2096 }
2097 ChannelState::Closing { .. } => {
2098 channel.state = ChannelState::Closed;
2099 }
2100 ChannelState::ClosingClientRelease => {
2101 channel.state = ChannelState::ClientReleased;
2102 self.check_disconnected();
2103 }
2104 ChannelState::ClosingReopen { request, .. } => {
2105 channel.state = ChannelState::Closed;
2106 self.open_channel(offer_id, &request, None);
2107 }
2108
2109 ChannelState::Closed
2110 | ChannelState::ClientReleased
2111 | ChannelState::Opening { .. }
2112 | ChannelState::Open { .. }
2113 | ChannelState::Revoked
2114 | ChannelState::Reoffered
2115 | ChannelState::OpeningClientRelease => {
2116 tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid close complete")
2117 }
2118 }
2119 }
2120
2121 fn send_close_reserved_channel_response(
2122 &mut self,
2123 channel_id: ChannelId,
2124 offer_id: OfferId,
2125 target: ConnectionTarget,
2126 ) {
2127 self.sender().send_message_with_target(
2128 &protocol::CloseReservedChannelResponse { channel_id },
2129 MessageTarget::ReservedChannel(offer_id, target),
2130 );
2131 }
2132
2133 fn handle_initiate_contact(
2136 &mut self,
2137 input: &protocol::InitiateContact2,
2138 message: &SynicMessage,
2139 includes_client_id: bool,
2140 ) -> Result<(), ChannelError> {
2141 let target_info =
2142 protocol::TargetInfo::from(input.initiate_contact.interrupt_page_or_target_info);
2143
2144 let target_sint = if message.multiclient
2145 && input.initiate_contact.version_requested >= Version::Win10Rs3_1 as u32
2146 {
2147 target_info.sint()
2148 } else {
2149 VMBUS_SINT
2150 };
2151
2152 let target_vtl = if message.multiclient
2153 && input.initiate_contact.version_requested >= Version::Win10Rs4 as u32
2154 {
2155 target_info.vtl()
2156 } else {
2157 0
2158 };
2159
2160 let feature_flags = if input.initiate_contact.version_requested >= Version::Copper as u32 {
2161 target_info.feature_flags()
2162 } else {
2163 0
2164 };
2165
2166 let target_message_vp =
2171 if input.initiate_contact.version_requested >= Version::Win8_1 as u32 {
2172 input.initiate_contact.target_message_vp
2173 } else {
2174 0
2175 };
2176
2177 let interrupt_page = (input.initiate_contact.version_requested < Version::Win8 as u32
2184 && input.initiate_contact.interrupt_page_or_target_info != 0)
2185 .then_some(input.initiate_contact.interrupt_page_or_target_info);
2186
2187 let monitor_page = if (input.initiate_contact.parent_to_child_monitor_page_gpa == 0)
2190 != (input.initiate_contact.child_to_parent_monitor_page_gpa == 0)
2191 {
2192 MonitorPageRequest::Invalid
2193 } else if input.initiate_contact.parent_to_child_monitor_page_gpa != 0 {
2194 MonitorPageRequest::Some(MonitorPageGpas {
2195 parent_to_child: input.initiate_contact.parent_to_child_monitor_page_gpa,
2196 child_to_parent: input.initiate_contact.child_to_parent_monitor_page_gpa,
2197 })
2198 } else {
2199 MonitorPageRequest::None
2200 };
2201
2202 let client_id = if FeatureFlags::from(feature_flags).client_id() {
2205 if includes_client_id {
2206 input.client_id
2207 } else {
2208 return Err(ChannelError::ParseError(
2209 protocol::ParseError::MessageTooSmall(Some(
2210 protocol::MessageType::INITIATE_CONTACT,
2211 )),
2212 ));
2213 }
2214 } else {
2215 Guid::ZERO
2216 };
2217
2218 let request = InitiateContactRequest {
2219 version_requested: input.initiate_contact.version_requested,
2220 target_message_vp,
2221 monitor_page,
2222 target_sint,
2223 target_vtl,
2224 feature_flags,
2225 interrupt_page,
2226 client_id,
2227 trusted: message.trusted,
2228 };
2229 self.initiate_contact(request);
2230 Ok(())
2231 }
2232
2233 pub fn initiate_contact(&mut self, request: InitiateContactRequest) {
2234 let vtl = self.inner.assigned_channels.vtl as u8;
2237 if request.target_vtl != vtl {
2238 self.notifier.forward_unhandled(request);
2240 return;
2241 }
2242
2243 if request.target_sint != VMBUS_SINT {
2244 tracelimit::warn_ratelimited!(
2245 target_vtl = request.target_vtl,
2246 target_sint = request.target_sint,
2247 version = request.version_requested,
2248 "unsupported multiclient request",
2249 );
2250
2251 self.send_version_response_with_target(
2253 None,
2254 MessageTarget::Custom(ConnectionTarget {
2255 vp: request.target_message_vp,
2256 sint: request.target_sint,
2257 }),
2258 );
2259
2260 return;
2261 }
2262
2263 if !self.request_disconnect(ConnectionAction::Reconnect {
2264 initiate_contact: request,
2265 }) {
2266 return;
2267 }
2268
2269 let Some(version) = self.check_version_supported(&request) else {
2270 tracelimit::warn_ratelimited!(
2271 vtl,
2272 version = request.version_requested,
2273 client_id = ?request.client_id,
2274 "Guest requested unsupported version"
2275 );
2276
2277 self.send_version_response(None);
2279 return;
2280 };
2281
2282 tracelimit::info_ratelimited!(
2283 vtl,
2284 ?version,
2285 client_id = ?request.client_id,
2286 trusted = request.trusted,
2287 "Guest negotiated version"
2288 );
2289
2290 let monitor_page = match request.monitor_page {
2293 MonitorPageRequest::Some(mp) => {
2294 if self.inner.require_server_allocated_mnf {
2295 if !version.feature_flags.server_specified_monitor_pages() {
2296 tracelimit::warn_ratelimited!(
2297 "guest-supplied monitor pages not supported; MNF will be disabled"
2298 );
2299 }
2300
2301 None
2302 } else {
2303 Some(mp)
2304 }
2305 }
2306 MonitorPageRequest::None => None,
2307 MonitorPageRequest::Invalid => {
2308 self.send_version_response(Some(VersionResponseData::new(
2310 version,
2311 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2312 )));
2313
2314 return;
2315 }
2316 };
2317
2318 self.inner.state = ConnectionState::Connecting {
2319 info: ConnectionInfo {
2320 version,
2321 trusted: request.trusted,
2322 interrupt_page: request.interrupt_page,
2323 monitor_page: monitor_page.map(MonitorPageGpaInfo::from_guest_gpas),
2324 target_message_vp: request.target_message_vp,
2325 modifying: false,
2326 offers_sent: false,
2327 client_id: request.client_id,
2328 paused: false,
2329 },
2330 next_action: ConnectionAction::None,
2331 };
2332
2333 if let Err(err) = self.notifier.modify_connection(ModifyConnectionRequest {
2336 version: Some(version),
2337 monitor_page: monitor_page.into(),
2338 interrupt_page: request.interrupt_page.into(),
2339 target_message_vp: Some(request.target_message_vp),
2340 notify_relay: true,
2341 }) {
2342 tracelimit::error_ratelimited!(?err, "server failed to change state");
2343 self.inner.state = ConnectionState::Disconnected;
2344 self.send_version_response(Some(VersionResponseData::new(
2345 version,
2346 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2347 )));
2348 }
2349 }
2350
2351 pub(crate) fn complete_initiate_contact(&mut self, response: ModifyConnectionResponse) {
2352 let ConnectionState::Connecting {
2353 mut info,
2354 next_action,
2355 } = self.inner.state
2356 else {
2357 panic!("Invalid state for completing InitiateContact.");
2358 };
2359
2360 const LOCAL_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
2364 .with_client_id(true)
2365 .with_confidential_channels(true);
2366
2367 let (relay_feature_flags, server_specified_monitor_page) = match response {
2368 ModifyConnectionResponse::Supported(
2370 protocol::ConnectionState::SUCCESSFUL,
2371 feature_flags,
2372 server_specified_monitor_page,
2373 ) => (feature_flags, server_specified_monitor_page),
2374 ModifyConnectionResponse::Supported(
2377 connection_state,
2378 feature_flags,
2379 server_specified_monitor_page,
2380 ) => {
2381 tracelimit::error_ratelimited!(
2382 ?connection_state,
2383 "initiate contact failed because relay request failed"
2384 );
2385
2386 info.version.feature_flags &= (feature_flags | LOCAL_FEATURE_FLAGS)
2389 .with_server_specified_monitor_pages(server_specified_monitor_page.is_some());
2390
2391 self.send_version_response(Some(VersionResponseData::new(
2392 info.version,
2393 connection_state,
2394 )));
2395 self.inner.state = ConnectionState::Disconnected;
2396 return;
2397 }
2398 ModifyConnectionResponse::Unsupported => {
2401 self.send_version_response(None);
2402 self.inner.state = ConnectionState::Disconnected;
2403 return;
2404 }
2405 ModifyConnectionResponse::Modified(_) => {
2406 panic!("Invalid response for completing InitiateContact.");
2407 }
2408 };
2409
2410 assert!(
2412 info.version.feature_flags.server_specified_monitor_pages()
2413 || server_specified_monitor_page.is_none()
2414 );
2415
2416 info.version.feature_flags &= relay_feature_flags | LOCAL_FEATURE_FLAGS;
2419
2420 if let Some(gpas) = server_specified_monitor_page {
2424 info.monitor_page = Some(MonitorPageGpaInfo::from_server_gpas(gpas));
2425 info.version
2426 .feature_flags
2427 .set_server_specified_monitor_pages(true);
2428 } else {
2429 info.version
2430 .feature_flags
2431 .set_server_specified_monitor_pages(false);
2432 }
2433
2434 let version = info.version;
2435 self.inner.state = ConnectionState::Connected(info);
2436
2437 self.send_version_response(Some(
2438 VersionResponseData::new(version, protocol::ConnectionState::SUCCESSFUL)
2439 .with_monitor_pages(server_specified_monitor_page),
2440 ));
2441 if !matches!(next_action, ConnectionAction::None) && self.request_disconnect(next_action) {
2442 self.do_next_action(next_action);
2443 }
2444 }
2445
2446 fn check_version_supported(&self, request: &InitiateContactRequest) -> Option<VersionInfo> {
2448 let version = SUPPORTED_VERSIONS
2449 .iter()
2450 .find(|v| request.version_requested == **v as u32)
2451 .copied()?;
2452
2453 if let Some(max_version) = self.inner.max_version {
2455 if version as u32 > max_version.version {
2456 return None;
2457 }
2458 }
2459
2460 let supported_flags = if version >= Version::Copper {
2461 let max_supported_flags =
2463 SUPPORTED_FEATURE_FLAGS.with_confidential_channels(request.trusted);
2464
2465 if let Some(max_version) = self.inner.max_version {
2467 max_supported_flags & max_version.feature_flags
2468 } else {
2469 max_supported_flags
2470 }
2471 } else {
2472 FeatureFlags::new()
2473 };
2474
2475 let feature_flags = supported_flags & request.feature_flags.into();
2476
2477 assert!(version >= Version::Copper || feature_flags == FeatureFlags::new());
2478 if feature_flags.into_bits() != request.feature_flags {
2479 tracelimit::info_ratelimited!(
2482 supported = feature_flags.into_bits(),
2483 requested = request.feature_flags,
2484 "guest requested unsupported feature flags."
2485 );
2486 }
2487
2488 Some(VersionInfo {
2489 version,
2490 feature_flags,
2491 })
2492 }
2493
2494 fn send_version_response(&mut self, data: Option<VersionResponseData>) {
2495 self.send_version_response_with_target(data, MessageTarget::Default);
2496 }
2497
2498 fn send_version_response_with_target(
2499 &mut self,
2500 data: Option<VersionResponseData>,
2501 target: MessageTarget,
2502 ) {
2503 enum VersionResponseType {
2504 PreCopper,
2505 Copper,
2506 CopperWithServerMnf,
2507 }
2508
2509 let mut response_copper_with_mnf = protocol::VersionResponse3::new_zeroed();
2510 let response_copper = &mut response_copper_with_mnf.version_response2;
2511 let response = &mut response_copper.version_response;
2512 let mut response_type = VersionResponseType::PreCopper;
2513 if let Some(data) = data {
2514 if data.state == protocol::ConnectionState::SUCCESSFUL
2517 || data.version.version >= Version::Win8
2518 {
2519 response.version_supported = 1;
2520 response.connection_state = data.state;
2521 response.selected_version_or_connection_id =
2522 if data.version.version >= Version::Win10Rs3_1 {
2523 self.inner.child_connection_id
2524 } else {
2525 data.version.version as u32
2526 };
2527
2528 if data.version.version >= Version::Copper {
2529 response_copper.supported_features = data.version.feature_flags.into();
2530 response_type = VersionResponseType::Copper;
2531 if let Some(monitor_page) = data.monitor_pages {
2532 assert!(data.version.feature_flags.server_specified_monitor_pages());
2533 response_copper_with_mnf.child_to_parent_monitor_page_gpa =
2534 monitor_page.child_to_parent;
2535 response_copper_with_mnf.parent_to_child_monitor_page_gpa =
2536 monitor_page.parent_to_child;
2537 response_type = VersionResponseType::CopperWithServerMnf;
2538 }
2539 }
2540 }
2541 }
2542
2543 match response_type {
2545 VersionResponseType::PreCopper => {
2546 self.sender().send_message_with_target(response, target)
2547 }
2548 VersionResponseType::Copper => self
2549 .sender()
2550 .send_message_with_target(response_copper, target),
2551 VersionResponseType::CopperWithServerMnf => self
2552 .sender()
2553 .send_message_with_target(&response_copper_with_mnf, target),
2554 }
2555 }
2556
2557 fn request_disconnect(&mut self, new_action: ConnectionAction) -> bool {
2560 assert!(!self.is_resetting());
2561
2562 let gpadls = &mut self.inner.gpadls;
2564 let vm_reset = matches!(new_action, ConnectionAction::Reset);
2565 self.inner.channels.retain(|offer_id, channel| {
2566 (!vm_reset && channel.state.is_reserved())
2568 || !Self::client_release_channel(
2569 self.inner
2570 .pending_messages
2571 .sender(self.notifier, self.inner.state.is_paused()),
2572 offer_id,
2573 channel,
2574 gpadls,
2575 &mut self.inner.incomplete_gpadls,
2576 &mut self.inner.assigned_channels,
2577 &mut self.inner.assigned_monitors,
2578 None,
2579 vm_reset,
2580 )
2581 });
2582
2583 match &mut self.inner.state {
2587 ConnectionState::Disconnected => {
2588 if vm_reset {
2590 if !self.are_channels_reset(true) {
2591 self.inner.state = ConnectionState::Disconnecting {
2592 next_action: ConnectionAction::Reset,
2593 modify_sent: false,
2594 };
2595 }
2596 } else {
2597 assert!(self.are_channels_reset(false));
2598 }
2599 }
2600
2601 ConnectionState::Connected { .. } => {
2602 if self.are_channels_reset(vm_reset) {
2603 self.notify_disconnect(new_action);
2604 } else {
2605 self.inner.state = ConnectionState::Disconnecting {
2606 next_action: new_action,
2607 modify_sent: false,
2608 };
2609 }
2610 }
2611
2612 ConnectionState::Connecting { next_action, .. }
2613 | ConnectionState::Disconnecting { next_action, .. } => {
2614 *next_action = new_action;
2615 }
2616 }
2617
2618 matches!(self.inner.state, ConnectionState::Disconnected)
2619 }
2620
2621 pub(crate) fn complete_disconnect(&mut self) {
2622 if let ConnectionState::Disconnecting {
2623 next_action,
2624 modify_sent,
2625 } = std::mem::replace(&mut self.inner.state, ConnectionState::Disconnected)
2626 {
2627 assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2628 if !modify_sent {
2629 tracelimit::warn_ratelimited!("unexpected modify response");
2630 }
2631
2632 self.inner.state = ConnectionState::Disconnected;
2633 self.do_next_action(next_action);
2634 } else {
2635 unreachable!("not ready for disconnect");
2636 }
2637 }
2638
2639 fn do_next_action(&mut self, action: ConnectionAction) {
2640 match action {
2641 ConnectionAction::None => {}
2642 ConnectionAction::Reset => {
2643 self.complete_reset();
2644 }
2645 ConnectionAction::SendUnloadComplete => {
2646 self.complete_unload();
2647 }
2648 ConnectionAction::Reconnect { initiate_contact } => {
2649 self.initiate_contact(initiate_contact);
2650 }
2651 ConnectionAction::SendFailedVersionResponse => {
2652 self.send_version_response(None);
2655 }
2656 }
2657 }
2658
2659 fn handle_unload(&mut self) {
2661 tracing::debug!(
2662 vtl = self.inner.assigned_channels.vtl as u8,
2663 state = ?self.inner.state,
2664 "VmBus received unload request from guest",
2665 );
2666
2667 if self.request_disconnect(ConnectionAction::SendUnloadComplete) {
2668 self.complete_unload();
2669 }
2670 }
2671
2672 fn complete_unload(&mut self) {
2673 self.notifier.unload_complete();
2674 if let Some(version) = self.inner.delayed_max_version.take() {
2675 self.inner.set_compatibility_version(version, false);
2676 }
2677
2678 self.sender().send_message(&protocol::UnloadComplete {});
2679 tracelimit::info_ratelimited!("Vmbus disconnected");
2680 }
2681
2682 fn handle_request_offers(&mut self) -> Result<(), ChannelError> {
2684 let ConnectionState::Connected(info) = &mut self.inner.state else {
2685 unreachable!(
2686 "in unexpected state {:?}, should be prevented by Message::parse()",
2687 self.inner.state
2688 );
2689 };
2690
2691 if info.offers_sent {
2692 return Err(ChannelError::OffersAlreadySent);
2693 }
2694
2695 info.offers_sent = true;
2696
2697 let mut sorted_channels: Vec<_> = self
2700 .inner
2701 .channels
2702 .iter_mut()
2703 .filter(|(_, channel)| !channel.state.is_reserved())
2704 .collect();
2705
2706 if self.inner.use_absolute_channel_order {
2707 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2708 (
2709 channel.offer.offer_order.unwrap_or(u64::MAX),
2710 channel.offer.interface_id,
2711 channel.offer.instance_id,
2712 )
2713 });
2714 } else {
2715 sorted_channels.sort_unstable_by_key(|(_, channel)| {
2716 (
2717 channel.offer.interface_id,
2718 channel.offer.offer_order.unwrap_or(u64::MAX),
2719 channel.offer.instance_id,
2720 )
2721 });
2722 }
2723
2724 for (offer_id, channel) in sorted_channels {
2725 assert!(matches!(channel.state, ChannelState::ClientReleased));
2726
2727 channel.prepare_channel(
2728 offer_id,
2729 &mut self.inner.assigned_channels,
2730 &mut self.inner.assigned_monitors,
2731 );
2732
2733 channel.state = ChannelState::Closed;
2734 self.inner
2735 .pending_messages
2736 .sender(self.notifier, info.paused)
2737 .send_offer(channel, info);
2738 }
2739 self.sender().send_message(&protocol::AllOffersDelivered {});
2740
2741 Ok(())
2742 }
2743
2744 #[must_use]
2747 fn gpadl_updated(
2748 mut sender: MessageSender<'_, N>,
2749 offer_id: OfferId,
2750 channel: &Channel,
2751 gpadl_id: GpadlId,
2752 gpadl: &Gpadl,
2753 ) -> bool {
2754 if channel.state.is_revoked() {
2755 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2756 sender.send_gpadl_created(channel_id, gpadl_id, protocol::STATUS_UNSUCCESSFUL);
2757 false
2758 } else {
2759 sender.notifier.notify(
2761 offer_id,
2762 Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
2763 );
2764 true
2765 }
2766 }
2767
2768 fn handle_gpadl_header_core(
2770 &mut self,
2771 input: &protocol::GpadlHeader,
2772 range: &[u8],
2773 ) -> Result<(), ChannelError> {
2774 let (offer_id, channel) = self
2776 .inner
2777 .channels
2778 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2779
2780 if channel.state.is_reserved() {
2783 return Err(ChannelError::ChannelReserved);
2784 }
2785
2786 let mut gpadl = Gpadl::new(input.count, input.len as usize / 8);
2788 let done = gpadl.append(range)?;
2789
2790 let gpadl = match self.inner.gpadls.entry((input.gpadl_id, offer_id)) {
2792 Entry::Vacant(entry) => entry.insert(gpadl),
2793 Entry::Occupied(_) => return Err(ChannelError::DuplicateGpadlId),
2794 };
2795
2796 if !done {
2802 match self.inner.incomplete_gpadls.entry(input.gpadl_id) {
2803 Entry::Vacant(entry) => {
2804 entry.insert(offer_id);
2805 }
2806 Entry::Occupied(_) => {
2807 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2808 tracelimit::error_ratelimited!(
2809 channel_id = ?input.channel_id,
2810 key = %channel.offer.key(),
2811 gpadl_id = ?input.gpadl_id,
2812 "duplicate in-progress gpadl ID",
2813 );
2814 return Err(ChannelError::DuplicateGpadlId);
2815 }
2816 }
2817 }
2818
2819 if done
2820 && !Self::gpadl_updated(
2821 self.inner
2822 .pending_messages
2823 .sender(self.notifier, self.inner.state.is_paused()),
2824 offer_id,
2825 channel,
2826 input.gpadl_id,
2827 gpadl,
2828 )
2829 {
2830 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
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 if !Self::gpadl_updated(
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 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2894 }
2895 }
2896 }
2897 Err(err) => {
2898 self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2899 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2900 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2901 tracelimit::warn_ratelimited!(
2902 err = &err as &dyn std::error::Error,
2903 channel_id = channel_id.0,
2904 key = %channel.offer.key(),
2905 gpadl_id = input.gpadl_id.0,
2906 "error handling gpadl body"
2907 );
2908 self.sender().send_gpadl_created(
2909 channel_id,
2910 input.gpadl_id,
2911 protocol::STATUS_UNSUCCESSFUL,
2912 );
2913 }
2914 }
2915
2916 Ok(())
2917 }
2918
2919 fn handle_gpadl_teardown(
2921 &mut self,
2922 input: &protocol::GpadlTeardown,
2923 ) -> Result<(), ChannelError> {
2924 let (offer_id, channel) = self
2925 .inner
2926 .channels
2927 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2928
2929 tracing::debug!(
2930 channel_id = input.channel_id.0,
2931 key = %channel.offer.key(),
2932 gpadl_id = input.gpadl_id.0,
2933 "Received GPADL teardown request"
2934 );
2935
2936 let gpadl = self
2937 .inner
2938 .gpadls
2939 .get_mut(&(input.gpadl_id, offer_id))
2940 .ok_or(ChannelError::UnknownGpadlId)?;
2941
2942 match gpadl.state {
2943 GpadlState::InProgress
2944 | GpadlState::Offered
2945 | GpadlState::OfferedTearingDown
2946 | GpadlState::TearingDown => {
2947 return Err(ChannelError::InvalidGpadlState);
2948 }
2949 GpadlState::Accepted => {
2950 if channel.info.as_ref().map(|info| info.channel_id) != Some(input.channel_id) {
2951 return Err(ChannelError::WrongGpadlChannelId);
2952 }
2953
2954 if channel.state.is_reserved() {
2958 return Err(ChannelError::ChannelReserved);
2959 }
2960
2961 if channel.state.is_revoked() {
2962 tracing::trace!(
2963 channel_id = input.channel_id.0,
2964 key = %channel.offer.key(),
2965 gpadl_id = input.gpadl_id.0,
2966 "Gpadl teardown for revoked channel"
2967 );
2968
2969 self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2970 self.sender().send_gpadl_torndown(input.gpadl_id);
2971 } else {
2972 gpadl.state = GpadlState::TearingDown;
2973 self.notifier.notify(
2974 offer_id,
2975 Action::TeardownGpadl {
2976 gpadl_id: input.gpadl_id,
2977 post_restore: false,
2978 },
2979 );
2980 }
2981 }
2982 }
2983 Ok(())
2984 }
2985
2986 fn open_channel(
2989 &mut self,
2990 offer_id: OfferId,
2991 input: &OpenRequest,
2992 reserved_state: Option<ReservedState>,
2993 ) {
2994 let channel = &mut self.inner.channels[offer_id];
2995 assert!(matches!(channel.state, ChannelState::Closed));
2996
2997 channel.state = ChannelState::Opening {
2998 request: *input,
2999 reserved_state,
3000 };
3001
3002 let info = channel.info.as_ref().expect("assigned");
3005 self.notifier.notify(
3006 offer_id,
3007 Action::Open(
3008 OpenParams::from_request(
3009 info,
3010 input,
3011 channel.handled_monitor_info(),
3012 reserved_state.map(|state| state.target),
3013 ),
3014 self.inner.state.get_version().expect("must be connected"),
3015 ),
3016 );
3017 }
3018
3019 fn handle_open_channel(&mut self, input: &protocol::OpenChannel2) -> Result<(), ChannelError> {
3021 let (offer_id, channel) = self
3022 .inner
3023 .channels
3024 .get_by_channel_id_mut(&self.inner.assigned_channels, input.open_channel.channel_id)?;
3025
3026 let guest_specified_interrupt_info = self
3027 .inner
3028 .state
3029 .check_feature_flags(|ff| ff.guest_specified_signal_parameters())
3030 .then_some(SignalInfo {
3031 event_flag: input.event_flag,
3032 connection_id: input.connection_id,
3033 });
3034
3035 let flags = if self
3036 .inner
3037 .state
3038 .check_feature_flags(|ff| ff.channel_interrupt_redirection())
3039 {
3040 input.flags
3041 } else {
3042 Default::default()
3043 };
3044
3045 let request = OpenRequest {
3046 open_id: input.open_channel.open_id,
3047 ring_buffer_gpadl_id: input.open_channel.ring_buffer_gpadl_id,
3048 target_vp: protocol::vp_index_if_enabled(input.open_channel.target_vp),
3049 downstream_ring_buffer_page_offset: input
3050 .open_channel
3051 .downstream_ring_buffer_page_offset,
3052 user_data: input.open_channel.user_data,
3053 guest_specified_interrupt_info,
3054 flags,
3055 };
3056
3057 match channel.state {
3058 ChannelState::Closed => self.open_channel(offer_id, &request, None),
3059 ChannelState::Closing { params, .. } => {
3060 channel.state = ChannelState::ClosingReopen { params, request }
3064 }
3065 ChannelState::Revoked | ChannelState::Reoffered => {}
3066
3067 ChannelState::Open { .. }
3068 | ChannelState::Opening { .. }
3069 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelAlreadyOpen),
3070
3071 ChannelState::ClientReleased
3072 | ChannelState::ClosingClientRelease
3073 | ChannelState::OpeningClientRelease => unreachable!(),
3074 }
3075 Ok(())
3076 }
3077
3078 fn handle_close_channel(&mut self, input: &protocol::CloseChannel) -> Result<(), ChannelError> {
3080 let (offer_id, channel) = self
3081 .inner
3082 .channels
3083 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3084
3085 match channel.state {
3086 ChannelState::Open {
3087 params,
3088 modify_state,
3089 reserved_state: None,
3090 } => {
3091 if modify_state.is_modifying() {
3092 tracelimit::warn_ratelimited!(
3093 key = %channel.offer.key(),
3094 ?modify_state,
3095 "Client is closing the channel with a modify in progress"
3096 )
3097 }
3098
3099 channel.state = ChannelState::Closing {
3100 params,
3101 reserved_state: None,
3102 };
3103 self.notifier.notify(offer_id, Action::Close);
3104 }
3105
3106 ChannelState::Open {
3107 reserved_state: Some(_),
3108 ..
3109 } => return Err(ChannelError::ChannelReserved),
3110
3111 ChannelState::Revoked | ChannelState::Reoffered => {}
3112
3113 ChannelState::Closed
3114 | ChannelState::Opening { .. }
3115 | ChannelState::Closing { .. }
3116 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3117
3118 ChannelState::ClientReleased
3119 | ChannelState::ClosingClientRelease
3120 | ChannelState::OpeningClientRelease => unreachable!(),
3121 }
3122
3123 Ok(())
3124 }
3125
3126 fn handle_open_reserved_channel(
3129 &mut self,
3130 input: &protocol::OpenReservedChannel,
3131 version: VersionInfo,
3132 ) -> Result<(), ChannelError> {
3133 let (offer_id, channel) = self
3134 .inner
3135 .channels
3136 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3137
3138 let target = ConnectionTarget {
3139 vp: input.target_vp,
3140 sint: input.target_sint as u8,
3141 };
3142
3143 let reserved_state = Some(ReservedState { version, target });
3144
3145 let request = OpenRequest {
3146 ring_buffer_gpadl_id: input.ring_buffer_gpadl,
3147 target_vp: None,
3149 downstream_ring_buffer_page_offset: input.downstream_page_offset,
3150 open_id: 0,
3151 user_data: UserDefinedData::new_zeroed(),
3152 guest_specified_interrupt_info: None,
3153 flags: Default::default(),
3154 };
3155
3156 match channel.state {
3157 ChannelState::Closed => self.open_channel(offer_id, &request, reserved_state),
3158 ChannelState::Revoked | ChannelState::Reoffered => {}
3159
3160 ChannelState::Open { .. } | ChannelState::Opening { .. } => {
3161 return Err(ChannelError::ChannelAlreadyOpen);
3162 }
3163
3164 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3165 return Err(ChannelError::InvalidChannelState);
3166 }
3167
3168 ChannelState::ClientReleased
3169 | ChannelState::ClosingClientRelease
3170 | ChannelState::OpeningClientRelease => unreachable!(),
3171 }
3172 Ok(())
3173 }
3174
3175 fn handle_close_reserved_channel(
3178 &mut self,
3179 input: &protocol::CloseReservedChannel,
3180 ) -> Result<(), ChannelError> {
3181 let (offer_id, channel) = self
3182 .inner
3183 .channels
3184 .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3185
3186 match channel.state {
3187 ChannelState::Open {
3188 params,
3189 reserved_state: Some(mut resvd),
3190 ..
3191 } => {
3192 resvd.target.vp = input.target_vp;
3193 resvd.target.sint = input.target_sint as u8;
3194 channel.state = ChannelState::Closing {
3195 params,
3196 reserved_state: Some(resvd),
3197 };
3198 self.notifier.notify(offer_id, Action::Close);
3199 }
3200
3201 ChannelState::Open {
3202 reserved_state: None,
3203 ..
3204 } => return Err(ChannelError::ChannelNotReserved),
3205
3206 ChannelState::Revoked | ChannelState::Reoffered => {}
3207
3208 ChannelState::Closed
3209 | ChannelState::Opening { .. }
3210 | ChannelState::Closing { .. }
3211 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3212
3213 ChannelState::ClientReleased
3214 | ChannelState::ClosingClientRelease
3215 | ChannelState::OpeningClientRelease => unreachable!(),
3216 }
3217
3218 Ok(())
3219 }
3220
3221 #[must_use]
3225 fn client_release_channel(
3226 mut sender: MessageSender<'_, N>,
3227 offer_id: OfferId,
3228 channel: &mut Channel,
3229 gpadls: &mut GpadlMap,
3230 incomplete_gpadls: &mut IncompleteGpadlMap,
3231 assigned_channels: &mut AssignedChannels,
3232 assigned_monitors: &mut AssignedMonitors,
3233 info: Option<&ConnectionInfo>,
3234 vm_reset: bool,
3235 ) -> bool {
3236 tracelimit::info_ratelimited!(?offer_id, key = %channel.offer.key(), "client released channel");
3237 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3239 if gpadl_offer_id != offer_id {
3240 return true;
3241 }
3242 match gpadl.state {
3243 GpadlState::InProgress => {
3244 incomplete_gpadls.remove(&gpadl_id);
3245 false
3246 }
3247 GpadlState::Offered => {
3248 gpadl.state = GpadlState::OfferedTearingDown;
3249 true
3250 }
3251 GpadlState::Accepted => {
3252 if channel.state.is_revoked() {
3253 false
3255 } else {
3256 gpadl.state = GpadlState::TearingDown;
3257 sender.notifier.notify(
3258 offer_id,
3259 Action::TeardownGpadl {
3260 gpadl_id,
3261 post_restore: false,
3262 },
3263 );
3264 true
3265 }
3266 }
3267 GpadlState::OfferedTearingDown | GpadlState::TearingDown => true,
3268 }
3269 });
3270
3271 let remove = match &mut channel.state {
3272 ChannelState::Closed => {
3273 channel.state = ChannelState::ClientReleased;
3274 false
3275 }
3276 ChannelState::Reoffered => {
3277 if let Some(info) = info {
3278 channel.state = ChannelState::Closed;
3279 channel.restore_state = RestoreState::New;
3280 sender.send_offer(channel, info);
3281 return false;
3283 }
3284 channel.state = ChannelState::ClientReleased;
3285 false
3286 }
3287 ChannelState::Revoked => {
3288 channel.state = ChannelState::ClientReleased;
3289 true
3290 }
3291 ChannelState::Opening { .. } => {
3292 if vm_reset {
3310 channel.state = ChannelState::ClientReleased;
3311 } else {
3312 channel.state = ChannelState::OpeningClientRelease;
3313 }
3314 false
3315 }
3316 ChannelState::Open { .. } => {
3317 channel.state = ChannelState::ClosingClientRelease;
3318 sender.notifier.notify(offer_id, Action::Close);
3319 false
3320 }
3321 ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3322 channel.state = ChannelState::ClosingClientRelease;
3323 false
3324 }
3325
3326 ChannelState::ClosingClientRelease
3327 | ChannelState::OpeningClientRelease
3328 | ChannelState::ClientReleased => false,
3329 };
3330
3331 assert!(channel.state.is_released());
3332
3333 channel.release_channel(offer_id, assigned_channels, assigned_monitors);
3334 remove
3335 }
3336
3337 fn handle_rel_id_released(
3339 &mut self,
3340 input: &protocol::RelIdReleased,
3341 ) -> Result<(), ChannelError> {
3342 let channel_id = input.channel_id;
3343 let (offer_id, channel) = self
3344 .inner
3345 .channels
3346 .get_by_channel_id_mut(&self.inner.assigned_channels, channel_id)?;
3347
3348 match channel.state {
3349 ChannelState::Closed
3350 | ChannelState::Revoked
3351 | ChannelState::Closing { .. }
3352 | ChannelState::Reoffered => {
3353 if Self::client_release_channel(
3354 self.inner
3355 .pending_messages
3356 .sender(self.notifier, self.inner.state.is_paused()),
3357 offer_id,
3358 channel,
3359 &mut self.inner.gpadls,
3360 &mut self.inner.incomplete_gpadls,
3361 &mut self.inner.assigned_channels,
3362 &mut self.inner.assigned_monitors,
3363 self.inner.state.get_connected_info(),
3364 false,
3365 ) {
3366 self.inner.channels.remove(offer_id);
3367 }
3368
3369 self.check_disconnected();
3370 }
3371
3372 ChannelState::Opening { .. }
3373 | ChannelState::Open { .. }
3374 | ChannelState::ClosingReopen { .. } => return Err(ChannelError::InvalidChannelState),
3375
3376 ChannelState::ClientReleased
3377 | ChannelState::OpeningClientRelease
3378 | ChannelState::ClosingClientRelease => unreachable!(),
3379 }
3380 Ok(())
3381 }
3382
3383 fn handle_tl_connect_request(&mut self, request: protocol::TlConnectRequest2) {
3386 let version = self
3387 .inner
3388 .state
3389 .get_version()
3390 .expect("must be connected")
3391 .version;
3392
3393 let hosted_silo_unaware = version < Version::Win10Rs5;
3394 self.notifier
3395 .notify_hvsock(&HvsockConnectRequest::from_message(
3396 request,
3397 hosted_silo_unaware,
3398 ));
3399 }
3400
3401 pub fn send_tl_connect_result(&mut self, result: HvsockConnectResult) {
3403 if !result.success && self.inner.state.check_version(Version::Win10Rs3_0) {
3407 self.sender().send_message(&protocol::TlConnectResult {
3411 service_id: result.service_id,
3412 endpoint_id: result.endpoint_id,
3413 status: protocol::STATUS_CONNECTION_REFUSED,
3414 })
3415 }
3416 }
3417
3418 fn handle_modify_channel(
3421 &mut self,
3422 request: &protocol::ModifyChannel,
3423 ) -> Result<(), ChannelError> {
3424 let result = self.modify_channel(request);
3425 if result.is_err() {
3426 self.send_modify_channel_response(request.channel_id, protocol::STATUS_UNSUCCESSFUL);
3427 }
3428
3429 result
3430 }
3431
3432 fn modify_channel(&mut self, request: &protocol::ModifyChannel) -> Result<(), ChannelError> {
3434 if request.target_vp == protocol::VP_INDEX_DISABLE_INTERRUPT {
3436 return Err(ChannelError::InvalidTargetVp);
3437 }
3438
3439 let (offer_id, channel) = self
3440 .inner
3441 .channels
3442 .get_by_channel_id_mut(&self.inner.assigned_channels, request.channel_id)?;
3443
3444 let (open_request, modify_state) = match &mut channel.state {
3445 ChannelState::Open {
3446 params,
3447 modify_state,
3448 reserved_state: None,
3449 } => (params, modify_state),
3450 _ => return Err(ChannelError::InvalidChannelState),
3451 };
3452
3453 if open_request.target_vp.is_none() {
3454 return Err(ChannelError::InterruptsDisabled);
3455 }
3456
3457 if let ModifyState::Modifying { pending_target_vp } = modify_state {
3458 if self.inner.state.check_version(Version::Iron) {
3459 tracelimit::warn_ratelimited!(
3462 key = %channel.offer.key(),
3463 "Client sent new ModifyChannel before receiving ModifyChannelResponse."
3464 );
3465 } else {
3466 *pending_target_vp = Some(request.target_vp);
3469 }
3470 } else {
3471 self.notifier.notify(
3472 offer_id,
3473 Action::Modify {
3474 target_vp: request.target_vp,
3475 },
3476 );
3477
3478 open_request.target_vp = Some(request.target_vp);
3480 *modify_state = ModifyState::Modifying {
3481 pending_target_vp: None,
3482 };
3483 }
3484
3485 Ok(())
3486 }
3487
3488 pub fn modify_channel_complete(&mut self, offer_id: OfferId, status: i32) {
3495 let channel = &mut self.inner.channels[offer_id];
3496
3497 if let ChannelState::Open {
3498 params,
3499 modify_state: ModifyState::Modifying { pending_target_vp },
3500 reserved_state: None,
3501 } = channel.state
3502 {
3503 channel.state = ChannelState::Open {
3504 params,
3505 modify_state: ModifyState::NotModifying,
3506 reserved_state: None,
3507 };
3508
3509 let channel_id = channel.info.as_ref().expect("assigned").channel_id;
3511 let key = channel.offer.key();
3512 self.send_modify_channel_response(channel_id, status);
3513
3514 if let Some(target_vp) = pending_target_vp {
3516 let request = protocol::ModifyChannel {
3517 channel_id,
3518 target_vp,
3519 };
3520
3521 if let Err(error) = self.handle_modify_channel(&request) {
3522 tracelimit::warn_ratelimited!(?error, %key, "Pending ModifyChannel request failed.")
3523 }
3524 }
3525 }
3526 }
3527
3528 fn send_modify_channel_response(&mut self, channel_id: ChannelId, status: i32) {
3529 if self.inner.state.check_version(Version::Iron) {
3530 self.sender()
3531 .send_message(&protocol::ModifyChannelResponse { channel_id, status });
3532 }
3533 }
3534
3535 fn handle_modify_connection(&mut self, request: protocol::ModifyConnection) {
3536 if let Err(err) = self.modify_connection(request) {
3537 tracelimit::error_ratelimited!(?err, "modifying connection failed");
3538 self.complete_modify_connection(ModifyConnectionResponse::Modified(
3539 protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
3540 ));
3541 }
3542 }
3543
3544 fn modify_connection(&mut self, request: protocol::ModifyConnection) -> anyhow::Result<()> {
3545 let ConnectionState::Connected(info) = &mut self.inner.state else {
3546 anyhow::bail!(
3547 "Invalid state for ModifyConnection request: {:?}",
3548 self.inner.state
3549 );
3550 };
3551
3552 if info.modifying {
3553 anyhow::bail!(
3554 "Duplicate ModifyConnection request, state: {:?}",
3555 self.inner.state
3556 );
3557 }
3558
3559 if matches!(
3560 info.monitor_page,
3561 Some(MonitorPageGpaInfo {
3562 server_allocated: true,
3563 ..
3564 })
3565 ) {
3566 anyhow::bail!("Cannot modify server-allocated monitor pages");
3567 }
3568
3569 if (request.child_to_parent_monitor_page_gpa == 0)
3570 != (request.parent_to_child_monitor_page_gpa == 0)
3571 {
3572 anyhow::bail!("Guest must specify either both or no monitor pages, {request:?}");
3573 }
3574
3575 let monitor_page = (request.child_to_parent_monitor_page_gpa != 0).then_some(
3576 MonitorPageGpaInfo::from_guest_gpas(MonitorPageGpas {
3577 child_to_parent: request.child_to_parent_monitor_page_gpa,
3578 parent_to_child: request.parent_to_child_monitor_page_gpa,
3579 }),
3580 );
3581
3582 info.modifying = true;
3583 info.monitor_page = monitor_page;
3584 tracing::debug!("modifying connection parameters.");
3585 self.notifier.modify_connection(request.into())?;
3586
3587 Ok(())
3588 }
3589
3590 pub fn complete_modify_connection(&mut self, response: ModifyConnectionResponse) {
3591 tracing::debug!(?response, "modifying connection parameters complete");
3592
3593 match &mut self.inner.state {
3597 ConnectionState::Connecting { .. } => self.complete_initiate_contact(response),
3598 ConnectionState::Disconnecting { .. } => self.complete_disconnect(),
3599 ConnectionState::Connected(info) => {
3600 let ModifyConnectionResponse::Modified(connection_state) = response else {
3601 panic!(
3602 "Relay should not return {:?} for a modify request with no version.",
3603 response
3604 );
3605 };
3606
3607 if !info.modifying {
3608 panic!(
3609 "ModifyConnection response while not modifying, state: {:?}",
3610 self.inner.state
3611 );
3612 }
3613
3614 info.modifying = false;
3615 self.sender()
3616 .send_message(&protocol::ModifyConnectionResponse { connection_state });
3617 }
3618 _ => panic!(
3619 "Invalid state for ModifyConnection response: {:?}",
3620 self.inner.state
3621 ),
3622 }
3623 }
3624
3625 fn handle_pause(&mut self) {
3626 tracelimit::info_ratelimited!("pausing sending messages");
3627 self.sender().send_message(&protocol::PauseResponse {});
3628 let ConnectionState::Connected(info) = &mut self.inner.state else {
3629 unreachable!(
3630 "in unexpected state {:?}, should be prevented by Message::parse()",
3631 self.inner.state
3632 );
3633 };
3634 info.paused = true;
3635 }
3636
3637 pub fn handle_synic_message(&mut self, message: SynicMessage) -> Result<(), ChannelError> {
3639 assert!(!self.is_resetting());
3640
3641 let version = self.inner.state.get_version();
3642 let msg = Message::parse(&message.data, version)?;
3643 tracing::trace!(?msg, message.trusted, "received vmbus message");
3644 if self.inner.state.is_trusted() && !message.trusted {
3649 tracelimit::warn_ratelimited!(?msg, "Received untrusted message");
3650 return Err(ChannelError::UntrustedMessage);
3651 }
3652
3653 match &mut self.inner.state {
3655 ConnectionState::Connected(info) if info.paused => {
3656 if !matches!(
3657 msg,
3658 Message::Resume(..)
3659 | Message::Unload(..)
3660 | Message::InitiateContact { .. }
3661 | Message::InitiateContact2 { .. }
3662 ) {
3663 tracelimit::warn_ratelimited!(?msg, "Received message while paused");
3664 return Err(ChannelError::Paused);
3665 }
3666 tracelimit::info_ratelimited!("resuming sending messages");
3667 info.paused = false;
3668 }
3669 _ => {}
3670 }
3671
3672 match msg {
3673 Message::InitiateContact2(input, ..) => {
3674 self.handle_initiate_contact(&input, &message, true)?
3675 }
3676 Message::InitiateContact(input, ..) => {
3677 self.handle_initiate_contact(&input.into(), &message, false)?
3678 }
3679 Message::Unload(..) => self.handle_unload(),
3680 Message::RequestOffers(..) => self.handle_request_offers()?,
3681 Message::GpadlHeader(input, range) => self.handle_gpadl_header(&input, range),
3682 Message::GpadlBody(input, range) => self.handle_gpadl_body(&input, range)?,
3683 Message::GpadlTeardown(input, ..) => self.handle_gpadl_teardown(&input)?,
3684 Message::OpenChannel(input, ..) => self.handle_open_channel(&input.into())?,
3685 Message::OpenChannel2(input, ..) => self.handle_open_channel(&input)?,
3686 Message::CloseChannel(input, ..) => self.handle_close_channel(&input)?,
3687 Message::RelIdReleased(input, ..) => self.handle_rel_id_released(&input)?,
3688 Message::TlConnectRequest(input, ..) => self.handle_tl_connect_request(input.into()),
3689 Message::TlConnectRequest2(input, ..) => self.handle_tl_connect_request(input),
3690 Message::ModifyChannel(input, ..) => self.handle_modify_channel(&input)?,
3691 Message::ModifyConnection(input, ..) => self.handle_modify_connection(input),
3692 Message::OpenReservedChannel(input, ..) => self.handle_open_reserved_channel(
3693 &input,
3694 version.expect("version validated by Message::parse"),
3695 )?,
3696 Message::CloseReservedChannel(input, ..) => {
3697 self.handle_close_reserved_channel(&input)?
3698 }
3699 Message::Pause(protocol::Pause, ..) => self.handle_pause(),
3700 Message::Resume(protocol::Resume, ..) => {}
3701 Message::OfferChannel(..)
3703 | Message::RescindChannelOffer(..)
3704 | Message::AllOffersDelivered(..)
3705 | Message::OpenResult(..)
3706 | Message::GpadlCreated(..)
3707 | Message::GpadlTorndown(..)
3708 | Message::VersionResponse(..)
3709 | Message::VersionResponse2(..)
3710 | Message::VersionResponse3(..)
3711 | Message::UnloadComplete(..)
3712 | Message::CloseReservedChannelResponse(..)
3713 | Message::TlConnectResult(..)
3714 | Message::ModifyChannelResponse(..)
3715 | Message::ModifyConnectionResponse(..)
3716 | Message::PauseResponse(..) => {
3717 unreachable!("Server received client message {:?}", msg);
3718 }
3719 }
3720 Ok(())
3721 }
3722
3723 pub fn gpadl_create_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId, status: i32) {
3725 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3726 tracelimit::error_ratelimited!(
3727 ?offer_id,
3728 key = %self.inner.channels[offer_id].offer.key(),
3729 ?gpadl_id,
3730 "invalid gpadl ID for channel"
3731 );
3732 return;
3733 };
3734 let retain = match gpadl.state {
3735 GpadlState::InProgress | GpadlState::TearingDown | GpadlState::Accepted => {
3736 tracelimit::error_ratelimited!(?offer_id, ?gpadl_id, ?gpadl, "invalid gpadl state");
3737 return;
3738 }
3739 GpadlState::Offered => {
3740 let channel_id = self.inner.channels[offer_id]
3741 .info
3742 .as_ref()
3743 .expect("assigned")
3744 .channel_id;
3745 self.inner
3746 .pending_messages
3747 .sender(self.notifier, self.inner.state.is_paused())
3748 .send_gpadl_created(channel_id, gpadl_id, status);
3749 if status >= 0 {
3750 gpadl.state = GpadlState::Accepted;
3751 true
3752 } else {
3753 false
3754 }
3755 }
3756 GpadlState::OfferedTearingDown => {
3757 if status >= 0 {
3758 self.notifier.notify(
3760 offer_id,
3761 Action::TeardownGpadl {
3762 gpadl_id,
3763 post_restore: false,
3764 },
3765 );
3766 gpadl.state = GpadlState::TearingDown;
3767 true
3768 } else {
3769 false
3770 }
3771 }
3772 };
3773 if !retain {
3774 self.inner
3775 .gpadls
3776 .remove(&(gpadl_id, offer_id))
3777 .expect("gpadl validated above");
3778
3779 self.check_disconnected();
3780 }
3781 }
3782
3783 pub fn gpadl_teardown_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId) {
3785 let channel = &mut self.inner.channels[offer_id];
3786 let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3787 tracelimit::error_ratelimited!(
3788 ?offer_id,
3789 key = %channel.offer.key(),
3790 ?gpadl_id,
3791 "invalid gpadl ID for channel"
3792 );
3793 return;
3794 };
3795 tracing::debug!(
3796 offer_id = offer_id.0,
3797 key = %channel.offer.key(),
3798 gpadl_id = gpadl_id.0,
3799 "Gpadl teardown complete"
3800 );
3801 match gpadl.state {
3802 GpadlState::InProgress
3803 | GpadlState::Offered
3804 | GpadlState::OfferedTearingDown
3805 | GpadlState::Accepted => {
3806 tracelimit::error_ratelimited!(?offer_id, key = %channel.offer.key(), ?gpadl_id, ?gpadl, "invalid gpadl state");
3807 }
3808 GpadlState::TearingDown => {
3809 if !channel.state.is_released() {
3810 self.sender().send_gpadl_torndown(gpadl_id);
3811 }
3812 self.inner
3813 .gpadls
3814 .remove(&(gpadl_id, offer_id))
3815 .expect("gpadl validated above");
3816
3817 self.check_disconnected();
3818 }
3819 }
3820 }
3821
3822 fn sender(&mut self) -> MessageSender<'_, N> {
3827 self.inner
3828 .pending_messages
3829 .sender(self.notifier, self.inner.state.is_paused())
3830 }
3831}
3832
3833fn revoke<N: Notifier>(
3834 mut sender: MessageSender<'_, N>,
3835 offer_id: OfferId,
3836 channel: &mut Channel,
3837 gpadls: &mut GpadlMap,
3838) -> bool {
3839 let info = match channel.state {
3840 ChannelState::Closed
3841 | ChannelState::Open { .. }
3842 | ChannelState::Opening { .. }
3843 | ChannelState::Closing { .. }
3844 | ChannelState::ClosingReopen { .. } => {
3845 channel.state = ChannelState::Revoked;
3846 Some(channel.info.as_ref().expect("assigned"))
3847 }
3848 ChannelState::Reoffered => {
3849 channel.state = ChannelState::Revoked;
3850 None
3851 }
3852 ChannelState::ClientReleased
3853 | ChannelState::OpeningClientRelease
3854 | ChannelState::ClosingClientRelease => None,
3855 ChannelState::Revoked => return true,
3857 };
3858 let retain = !channel.state.is_released();
3859
3860 gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3862 if gpadl_offer_id != offer_id {
3863 return true;
3864 }
3865
3866 match gpadl.state {
3867 GpadlState::InProgress => true,
3868 GpadlState::Offered => {
3869 if let Some(info) = info {
3870 sender.send_gpadl_created(
3871 info.channel_id,
3872 gpadl_id,
3873 protocol::STATUS_UNSUCCESSFUL,
3874 );
3875 }
3876 false
3877 }
3878 GpadlState::OfferedTearingDown => false,
3879 GpadlState::Accepted => true,
3880 GpadlState::TearingDown => {
3881 if info.is_some() {
3882 sender.send_gpadl_torndown(gpadl_id);
3883 }
3884 false
3885 }
3886 }
3887 });
3888 if let Some(info) = info {
3889 sender.send_rescind(info);
3890 }
3891 if channel.restore_state != RestoreState::New {
3893 channel.restore_state = RestoreState::Restored;
3894 }
3895 retain
3896}
3897
3898struct PendingMessages(VecDeque<OutgoingMessage>);
3899
3900impl PendingMessages {
3901 fn sender<'a, N: Notifier>(
3903 &'a mut self,
3904 notifier: &'a mut N,
3905 is_paused: bool,
3906 ) -> MessageSender<'a, N> {
3907 MessageSender {
3908 notifier,
3909 pending_messages: self,
3910 is_paused,
3911 }
3912 }
3913}
3914
3915struct MessageSender<'a, N> {
3918 notifier: &'a mut N,
3919 pending_messages: &'a mut PendingMessages,
3920 is_paused: bool,
3921}
3922
3923impl<N: Notifier> MessageSender<'_, N> {
3924 fn send_message<
3926 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3927 >(
3928 &mut self,
3929 msg: &T,
3930 ) {
3931 let message = OutgoingMessage::new(msg);
3932
3933 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3934 if !self.pending_messages.0.is_empty()
3936 || self.is_paused
3937 || !self.notifier.send_message(&message, MessageTarget::Default)
3938 {
3939 tracing::trace!("message queued");
3940 self.pending_messages.0.push_back(message);
3942 }
3943 }
3944
3945 fn send_message_with_target<
3947 T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3948 >(
3949 &mut self,
3950 msg: &T,
3951 target: MessageTarget,
3952 ) {
3953 if target == MessageTarget::Default {
3954 self.send_message(msg);
3955 } else {
3956 tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3957 let message = OutgoingMessage::new(msg);
3960 if !self.notifier.send_message(&message, target) {
3961 tracelimit::warn_ratelimited!(?target, "failed to send message");
3962 }
3963 }
3964 }
3965
3966 fn send_offer(&mut self, channel: &mut Channel, connection_info: &ConnectionInfo) {
3968 let info = channel.info.as_ref().expect("assigned");
3969 let mut flags = channel.offer.flags;
3970 if !connection_info
3971 .version
3972 .feature_flags
3973 .confidential_channels()
3974 {
3975 flags.set_confidential_ring_buffer(false);
3976 flags.set_confidential_external_memory(false);
3977 }
3978
3979 let monitor_id = connection_info.monitor_page.and(info.monitor_id);
3986 let msg = protocol::OfferChannel {
3987 interface_id: channel.offer.interface_id,
3988 instance_id: channel.offer.instance_id,
3989 rsvd: [0; 4],
3990 flags,
3991 mmio_megabytes: channel.offer.mmio_megabytes,
3992 user_defined: channel.offer.user_defined,
3993 subchannel_index: channel.offer.subchannel_index,
3994 mmio_megabytes_optional: channel.offer.mmio_megabytes_optional,
3995 channel_id: info.channel_id,
3996 monitor_id: monitor_id.unwrap_or(MonitorId::INVALID).0,
3997 monitor_allocated: monitor_id.is_some().into(),
3998 is_dedicated: 1,
4001 connection_id: info.connection_id,
4002 };
4003 tracing::info!(
4004 channel_id = msg.channel_id.0,
4005 connection_id = msg.connection_id,
4006 key = %channel.offer.key(),
4007 "sending offer to guest"
4008 );
4009
4010 self.send_message(&msg);
4011 }
4012
4013 fn send_open_result(
4014 &mut self,
4015 channel_id: ChannelId,
4016 open_request: &OpenRequest,
4017 result: i32,
4018 target: MessageTarget,
4019 ) {
4020 self.send_message_with_target(
4021 &protocol::OpenResult {
4022 channel_id,
4023 open_id: open_request.open_id,
4024 status: result as u32,
4025 },
4026 target,
4027 );
4028 }
4029
4030 fn send_gpadl_created(&mut self, channel_id: ChannelId, gpadl_id: GpadlId, status: i32) {
4031 self.send_message(&protocol::GpadlCreated {
4032 channel_id,
4033 gpadl_id,
4034 status,
4035 });
4036 }
4037
4038 fn send_gpadl_torndown(&mut self, gpadl_id: GpadlId) {
4039 self.send_message(&protocol::GpadlTorndown { gpadl_id });
4040 }
4041
4042 fn send_rescind(&mut self, info: &OfferedInfo) {
4043 tracing::info!(
4044 channel_id = info.channel_id.0,
4045 "rescinding channel from guest"
4046 );
4047
4048 self.send_message(&protocol::RescindChannelOffer {
4049 channel_id: info.channel_id,
4050 });
4051 }
4052}
4053
4054struct VersionResponseData {
4056 version: VersionInfo,
4057 state: protocol::ConnectionState,
4058 monitor_pages: Option<MonitorPageGpas>,
4059}
4060
4061impl VersionResponseData {
4062 fn new(version: VersionInfo, state: protocol::ConnectionState) -> Self {
4064 VersionResponseData {
4065 version,
4066 state,
4067 monitor_pages: None,
4068 }
4069 }
4070
4071 fn with_monitor_pages(mut self, monitor_pages: Option<MonitorPageGpas>) -> Self {
4073 self.monitor_pages = monitor_pages;
4074 self
4075 }
4076}