protocol.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //! This module defines the socket device protocol according to the virtio spec v1.1 5.10 Socket Device
  2. use super::error::{self, SocketError};
  3. use crate::volatile::ReadOnly;
  4. use core::{
  5. convert::{TryFrom, TryInto},
  6. fmt,
  7. mem::size_of,
  8. };
  9. use zerocopy::{
  10. byteorder::{LittleEndian, U16, U32, U64},
  11. AsBytes, FromBytes,
  12. };
  13. /// Currently only stream sockets are supported. type is 1 for stream socket types.
  14. #[derive(Copy, Clone, Debug)]
  15. #[repr(u16)]
  16. pub enum SocketType {
  17. /// Stream sockets provide in-order, guaranteed, connection-oriented delivery without message boundaries.
  18. Stream = 1,
  19. }
  20. impl From<SocketType> for U16<LittleEndian> {
  21. fn from(socket_type: SocketType) -> Self {
  22. (socket_type as u16).into()
  23. }
  24. }
  25. /// VirtioVsockConfig is the vsock device configuration space.
  26. #[repr(C)]
  27. pub struct VirtioVsockConfig {
  28. /// The guest_cid field contains the guest’s context ID, which uniquely identifies
  29. /// the device for its lifetime. The upper 32 bits of the CID are reserved and zeroed.
  30. ///
  31. /// According to virtio spec v1.1 2.4.1 Driver Requirements: Device Configuration Space,
  32. /// drivers MUST NOT assume reads from fields greater than 32 bits wide are atomic.
  33. /// So we need to split the u64 guest_cid into two parts.
  34. pub guest_cid_low: ReadOnly<u32>,
  35. pub guest_cid_high: ReadOnly<u32>,
  36. }
  37. /// The message header for data packets sent on the tx/rx queues
  38. #[repr(packed)]
  39. #[derive(AsBytes, Clone, Copy, Debug, FromBytes)]
  40. pub struct VirtioVsockHdr {
  41. pub src_cid: U64<LittleEndian>,
  42. pub dst_cid: U64<LittleEndian>,
  43. pub src_port: U32<LittleEndian>,
  44. pub dst_port: U32<LittleEndian>,
  45. pub len: U32<LittleEndian>,
  46. pub socket_type: U16<LittleEndian>,
  47. pub op: U16<LittleEndian>,
  48. pub flags: U32<LittleEndian>,
  49. pub buf_alloc: U32<LittleEndian>,
  50. pub fwd_cnt: U32<LittleEndian>,
  51. }
  52. impl Default for VirtioVsockHdr {
  53. fn default() -> Self {
  54. Self {
  55. src_cid: 0.into(),
  56. dst_cid: 0.into(),
  57. src_port: 0.into(),
  58. dst_port: 0.into(),
  59. len: 0.into(),
  60. socket_type: SocketType::Stream.into(),
  61. op: 0.into(),
  62. flags: 0.into(),
  63. buf_alloc: 0.into(),
  64. fwd_cnt: 0.into(),
  65. }
  66. }
  67. }
  68. #[derive(Clone, Debug)]
  69. pub struct VirtioVsockPacket<'a> {
  70. pub hdr: VirtioVsockHdr,
  71. pub data: &'a [u8],
  72. }
  73. impl<'a> VirtioVsockPacket<'a> {
  74. pub fn read_from(buffer: &'a [u8]) -> error::Result<Self> {
  75. let hdr = VirtioVsockHdr::read_from_prefix(buffer).ok_or(SocketError::BufferTooShort)?;
  76. let data_end = size_of::<VirtioVsockHdr>() + (hdr.len.get() as usize);
  77. let data = buffer
  78. .get(size_of::<VirtioVsockHdr>()..data_end)
  79. .ok_or(SocketError::BufferTooShort)?;
  80. Ok(Self { hdr, data })
  81. }
  82. pub fn op(&self) -> error::Result<VirtioVsockOp> {
  83. self.hdr.op.try_into()
  84. }
  85. }
  86. /// An event sent to the event queue
  87. #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes)]
  88. #[repr(C)]
  89. pub struct VirtioVsockEvent {
  90. // ID from the virtio_vsock_event_id struct in the virtio spec
  91. pub id: U32<LittleEndian>,
  92. }
  93. #[derive(Copy, Clone, Eq, PartialEq)]
  94. #[repr(u16)]
  95. pub enum VirtioVsockOp {
  96. Invalid = 0,
  97. /* Connect operations */
  98. Request = 1,
  99. Response = 2,
  100. Rst = 3,
  101. Shutdown = 4,
  102. /* To send payload */
  103. Rw = 5,
  104. /* Tell the peer our credit info */
  105. CreditUpdate = 6,
  106. /* Request the peer to send the credit info to us */
  107. CreditRequest = 7,
  108. }
  109. impl From<VirtioVsockOp> for U16<LittleEndian> {
  110. fn from(op: VirtioVsockOp) -> Self {
  111. (op as u16).into()
  112. }
  113. }
  114. impl TryFrom<U16<LittleEndian>> for VirtioVsockOp {
  115. type Error = SocketError;
  116. fn try_from(v: U16<LittleEndian>) -> Result<Self, Self::Error> {
  117. let op = match u16::from(v) {
  118. 0 => Self::Invalid,
  119. 1 => Self::Request,
  120. 2 => Self::Response,
  121. 3 => Self::Rst,
  122. 4 => Self::Shutdown,
  123. 5 => Self::Rw,
  124. 6 => Self::CreditUpdate,
  125. 7 => Self::CreditRequest,
  126. _ => return Err(SocketError::UnknownOperation(v.into())),
  127. };
  128. Ok(op)
  129. }
  130. }
  131. impl fmt::Debug for VirtioVsockOp {
  132. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  133. match self {
  134. Self::Invalid => write!(f, "VIRTIO_VSOCK_OP_INVALID"),
  135. Self::Request => write!(f, "VIRTIO_VSOCK_OP_REQUEST"),
  136. Self::Response => write!(f, "VIRTIO_VSOCK_OP_RESPONSE"),
  137. Self::Rst => write!(f, "VIRTIO_VSOCK_OP_RST"),
  138. Self::Shutdown => write!(f, "VIRTIO_VSOCK_OP_SHUTDOWN"),
  139. Self::Rw => write!(f, "VIRTIO_VSOCK_OP_RW"),
  140. Self::CreditUpdate => write!(f, "VIRTIO_VSOCK_OP_CREDIT_UPDATE"),
  141. Self::CreditRequest => write!(f, "VIRTIO_VSOCK_OP_CREDIT_REQUEST"),
  142. }
  143. }
  144. }