diff --git a/lib/propolis/src/hw/virtio/vsock.rs b/lib/propolis/src/hw/virtio/vsock.rs index f39b47c30..7d9f0ca86 100644 --- a/lib/propolis/src/hw/virtio/vsock.rs +++ b/lib/propolis/src/hw/virtio/vsock.rs @@ -19,6 +19,7 @@ use crate::vmm::MemCtx; use crate::vsock::packet::VsockPacket; use crate::vsock::packet::VsockPacketError; use crate::vsock::packet::VsockPacketHeader; +use crate::vsock::probes; use crate::vsock::proxy::VsockPortMapping; use crate::vsock::GuestCid; use crate::vsock::VsockBackend; @@ -84,6 +85,7 @@ impl RxPermit<'_> { }); } + probes::vsock_pkt_rx!(|| header); queue.push_used(&mut chain, &mem); } } diff --git a/lib/propolis/src/vsock/mod.rs b/lib/propolis/src/vsock/mod.rs index 64ec0c57f..2e938bc9b 100644 --- a/lib/propolis/src/vsock/mod.rs +++ b/lib/propolis/src/vsock/mod.rs @@ -55,3 +55,13 @@ pub enum VsockError { pub trait VsockBackend: Send + Sync + 'static { fn queue_notify(&self, queue_id: u16) -> Result<(), VsockError>; } + +#[usdt::provider(provider = "propolis")] +mod probes { + use crate::vsock::packet::VsockPacketHeader; + + /// Host->Guest + fn vsock_pkt_rx(hdr: &VsockPacketHeader) {} + /// Guest->Host + fn vsock_pkt_tx(hdr: &VsockPacketHeader) {} +} diff --git a/lib/propolis/src/vsock/packet.rs b/lib/propolis/src/vsock/packet.rs index 84c9ef5a0..f34eea27b 100644 --- a/lib/propolis/src/vsock/packet.rs +++ b/lib/propolis/src/vsock/packet.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +use serde::{Serialize, Serializer}; use strum::FromRepr; use zerocopy::byteorder::little_endian::{U16, U32, U64}; use zerocopy::{FromBytes, Immutable, IntoBytes}; @@ -11,7 +12,7 @@ use crate::vsock::{GuestCid, VSOCK_HOST_CID}; bitflags! { /// Shutdown flags for VIRTIO_VSOCK_OP_SHUTDOWN - #[derive(Clone, Copy, Debug, PartialEq, Eq)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] #[repr(transparent)] pub struct VsockPacketFlags: u32 { const VIRTIO_VSOCK_SHUTDOWN_F_RECEIVE = 1 << 0; @@ -19,7 +20,7 @@ bitflags! { } } -#[derive(Debug, Clone, Copy, FromRepr, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, FromRepr, PartialEq, Eq, Serialize)] #[repr(u16)] pub enum VsockSocketType { Stream = 1, @@ -52,7 +53,7 @@ pub enum VsockPacketError { InvalidDstCid { dst_cid: u64 }, } -#[derive(Clone, Copy, Debug, FromRepr, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, FromRepr, Eq, PartialEq, Serialize)] #[repr(u16)] pub enum VsockPacketOp { Request = 1, @@ -90,6 +91,28 @@ pub struct VsockPacketHeader { fwd_cnt: U32, } +// NB: This implementation is here to support dtrace usdt probes. +impl Serialize for VsockPacketHeader { + fn serialize( + &self, + serializer: S, + ) -> Result { + use serde::ser::SerializeStruct; + let mut s = serializer.serialize_struct("VsockPacketHeader", 10)?; + s.serialize_field("src_cid", &self.src_cid.get())?; + s.serialize_field("dst_cid", &self.dst_cid.get())?; + s.serialize_field("src_port", &self.src_port.get())?; + s.serialize_field("dst_port", &self.dst_port.get())?; + s.serialize_field("len", &self.len.get())?; + s.serialize_field("socket_type", &self.socket_type())?; + s.serialize_field("op", &self.op())?; + s.serialize_field("flags", &self.flags())?; + s.serialize_field("buf_alloc", &self.buf_alloc.get())?; + s.serialize_field("fwd_cnt", &self.fwd_cnt.get())?; + s.end() + } +} + impl VsockPacketHeader { pub fn src_cid(&self) -> u64 { self.src_cid.get() diff --git a/lib/propolis/src/vsock/poller.rs b/lib/propolis/src/vsock/poller.rs index aa260def3..0954475d8 100644 --- a/lib/propolis/src/vsock/poller.rs +++ b/lib/propolis/src/vsock/poller.rs @@ -22,6 +22,7 @@ use crate::hw::virtio::vsock::VSOCK_TX_QUEUE; use crate::vsock::packet::VsockPacket; use crate::vsock::packet::VsockPacketFlags; use crate::vsock::packet::VsockSocketType; +use crate::vsock::probes; use crate::vsock::proxy::ConnKey; use crate::vsock::proxy::VsockPortMapping; use crate::vsock::proxy::VsockProxyConn; @@ -302,6 +303,7 @@ impl VsockPoller { } }; + probes::vsock_pkt_tx!(|| &packet.header); // If the packet is not destined for the host drop it. if packet.header.dst_cid() != VSOCK_HOST_CID { warn!(