Struct virtio_vsock::packet::VsockPacket
source · pub struct VsockPacket<'a, B: BitmapSlice> { /* private fields */ }Expand description
The vsock packet, implemented as a wrapper over a virtio descriptor chain:
- the chain head, holding the packet header;
- an optional data/buffer descriptor, only present for data packets (for VSOCK_OP_RW requests).
Implementations§
source§impl<'a, B: BitmapSlice> VsockPacket<'a, B>
impl<'a, B: BitmapSlice> VsockPacket<'a, B>
sourcepub fn header_slice(&self) -> &VolatileSlice<'a, B>
pub fn header_slice(&self) -> &VolatileSlice<'a, B>
Return a reference to the header_slice of the packet.
sourcepub fn data_slice(&self) -> Option<&VolatileSlice<'a, B>>
pub fn data_slice(&self) -> Option<&VolatileSlice<'a, B>>
Return a reference to the data_slice of the packet.
sourcepub fn set_header_from_raw(&mut self, bytes: &[u8]) -> Result<()>
pub fn set_header_from_raw(&mut self, bytes: &[u8]) -> Result<()>
Write to the packet header from an input of raw bytes.
§Example
use virtio_vsock::packet::{VsockPacket, PKT_HEADER_SIZE};
const MAX_PKT_BUF_SIZE: u32 = 64 * 1024;
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10_0000)]).unwrap();
// Create a queue and populate it with a descriptor chain.
let mut queue = create_queue_with_chain(&mem);
while let Some(mut head) = queue.pop_descriptor_chain(&mem) {
let mut pkt = VsockPacket::from_rx_virtq_chain(&mem, &mut head, MAX_PKT_BUF_SIZE).unwrap();
pkt.set_header_from_raw(&[0u8; PKT_HEADER_SIZE]).unwrap();
}sourcepub fn set_src_cid(&mut self, cid: u64) -> &mut Self
pub fn set_src_cid(&mut self, cid: u64) -> &mut Self
Set the src_cid of the header.
sourcepub fn set_dst_cid(&mut self, cid: u64) -> &mut Self
pub fn set_dst_cid(&mut self, cid: u64) -> &mut Self
Set the dst_cid of the header.
sourcepub fn set_src_port(&mut self, port: u32) -> &mut Self
pub fn set_src_port(&mut self, port: u32) -> &mut Self
Set the src_port of the header.
sourcepub fn set_dst_port(&mut self, port: u32) -> &mut Self
pub fn set_dst_port(&mut self, port: u32) -> &mut Self
Set the dst_port of the header.
sourcepub fn set_buf_alloc(&mut self, buf_alloc: u32) -> &mut Self
pub fn set_buf_alloc(&mut self, buf_alloc: u32) -> &mut Self
Set the buf_alloc of the header.
sourcepub fn set_fwd_cnt(&mut self, fwd_cnt: u32) -> &mut Self
pub fn set_fwd_cnt(&mut self, fwd_cnt: u32) -> &mut Self
Set the fwd_cnt of the header.
sourcepub fn from_tx_virtq_chain<M, T>(
mem: &'a M,
desc_chain: &mut DescriptorChain<T>,
max_data_size: u32,
) -> Result<Self>where
M: GuestMemory,
<<M as GuestMemory>::R as GuestMemoryRegion>::B: WithBitmapSlice<'a, S = B>,
T: Deref,
T::Target: GuestMemory,
pub fn from_tx_virtq_chain<M, T>(
mem: &'a M,
desc_chain: &mut DescriptorChain<T>,
max_data_size: u32,
) -> Result<Self>where
M: GuestMemory,
<<M as GuestMemory>::R as GuestMemoryRegion>::B: WithBitmapSlice<'a, S = B>,
T: Deref,
T::Target: GuestMemory,
Create the packet wrapper from a TX chain.
The chain head is expected to hold a valid packet header. A following packet data descriptor can optionally end the chain.
§Arguments
mem- theGuestMemoryobject that can be used to access the queue buffers.desc_chain- the descriptor chain corresponding to a packet.max_data_size- the maximum size allowed for the packet payload, that was negotiated between the device and the driver. Tracking issue for defining this feature in virtio-spec here.
§Example
use virtio_vsock::packet::{VsockPacket, PKT_HEADER_SIZE};
const MAX_PKT_BUF_SIZE: u32 = 64 * 1024;
const OP_RW: u16 = 5;
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
// Create a queue and populate it with a descriptor chain.
let mut queue = create_queue_with_chain(&mem);
while let Some(mut head) = queue.pop_descriptor_chain(&mem) {
let pkt = match VsockPacket::from_tx_virtq_chain(&mem, &mut head, MAX_PKT_BUF_SIZE) {
Ok(pkt) => pkt,
Err(_e) => {
// Do some error handling.
queue.add_used(&mem, head.head_index(), 0);
continue;
}
};
// Here we would send the packet to the backend. Depending on the operation type, a
// different type of action will be done.
// For example, if it's a RW packet, we will forward the packet payload to the backend.
if pkt.op() == OP_RW {
// Send the packet payload to the backend.
}
queue.add_used(&mem, head.head_index(), 0);
}sourcepub fn from_rx_virtq_chain<M, T>(
mem: &'a M,
desc_chain: &mut DescriptorChain<T>,
max_data_size: u32,
) -> Result<Self>where
M: GuestMemory,
<<M as GuestMemory>::R as GuestMemoryRegion>::B: WithBitmapSlice<'a, S = B>,
T: Deref,
T::Target: GuestMemory,
pub fn from_rx_virtq_chain<M, T>(
mem: &'a M,
desc_chain: &mut DescriptorChain<T>,
max_data_size: u32,
) -> Result<Self>where
M: GuestMemory,
<<M as GuestMemory>::R as GuestMemoryRegion>::B: WithBitmapSlice<'a, S = B>,
T: Deref,
T::Target: GuestMemory,
Create the packet wrapper from an RX chain.
There must be two descriptors in the chain, both writable: a header descriptor and a data descriptor.
§Arguments
mem- theGuestMemoryobject that can be used to access the queue buffers.desc_chain- the descriptor chain corresponding to a packet.max_data_size- the maximum size allowed for the packet payload, that was negotiated between the device and the driver. Tracking issue for defining this feature in virtio-spec here.
§Example
use virtio_vsock::packet::{VsockPacket, PKT_HEADER_SIZE};
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
// Create a queue and populate it with a descriptor chain.
let mut queue = create_queue_with_chain(&mem);
while let Some(mut head) = queue.pop_descriptor_chain(&mem) {
let used_len = match VsockPacket::from_rx_virtq_chain(&mem, &mut head, MAX_PKT_BUF_SIZE) {
Ok(mut pkt) => {
// Make sure the header is zeroed out first.
pkt.header_slice()
.write(&[0u8; PKT_HEADER_SIZE], 0)
.unwrap();
// Write data to the packet, using the setters.
pkt.set_src_cid(SRC_CID)
.set_dst_cid(DST_CID)
.set_src_port(SRC_PORT)
.set_dst_port(DST_PORT)
.set_type(TYPE_STREAM)
.set_buf_alloc(BUF_ALLOC)
.set_fwd_cnt(FWD_CNT);
// In this example, we are sending a RW packet.
pkt.data_slice()
.unwrap()
.write_slice(&[1u8; LEN as usize], 0);
pkt.set_op(OP_RW).set_len(LEN);
pkt.header_slice().len() as u32 + LEN
}
Err(_e) => {
// Do some error handling.
0
}
};
queue.add_used(&mem, head.head_index(), used_len);
}source§impl<'a> VsockPacket<'a, ()>
impl<'a> VsockPacket<'a, ()>
sourcepub unsafe fn new(
header: &mut [u8],
data: Option<&mut [u8]>,
) -> Result<VsockPacket<'a, ()>>
pub unsafe fn new( header: &mut [u8], data: Option<&mut [u8]>, ) -> Result<VsockPacket<'a, ()>>
Create a packet based on one pointer for the header, and an optional one for data.
§Safety
To use this safely, the caller must guarantee that the memory pointed to by the hdr and
data slices is available for the duration of the lifetime of the new VolatileSlice. The
caller must also guarantee that all other users of the given chunk of memory are using
volatile accesses.
§Example
use virtio_vsock::packet::{VsockPacket, PKT_HEADER_SIZE};
const LEN: usize = 16;
let mut pkt_raw = [0u8; PKT_HEADER_SIZE + LEN];
let (hdr_raw, data_raw) = pkt_raw.split_at_mut(PKT_HEADER_SIZE);
// Safe because `hdr_raw` and `data_raw` live for as long as the scope of the current
// example.
let packet = unsafe { VsockPacket::new(hdr_raw, Some(data_raw)).unwrap() };