1 //! This module defines the socket device protocol according to the virtio spec v1.1 5.10 Socket Device
2 
3 use super::error::{self, SocketError};
4 use crate::volatile::ReadOnly;
5 use bitflags::bitflags;
6 use core::{
7     convert::{TryFrom, TryInto},
8     fmt,
9 };
10 use zerocopy::{
11     byteorder::{LittleEndian, U16, U32, U64},
12     AsBytes, FromBytes, FromZeroes,
13 };
14 
15 /// Well-known CID for the host.
16 pub const VMADDR_CID_HOST: u64 = 2;
17 
18 /// Currently only stream sockets are supported. type is 1 for stream socket types.
19 #[derive(Copy, Clone, Debug)]
20 #[repr(u16)]
21 pub enum SocketType {
22     /// Stream sockets provide in-order, guaranteed, connection-oriented delivery without message boundaries.
23     Stream = 1,
24     /// seqpacket socket type introduced in virtio-v1.2.
25     SeqPacket = 2,
26 }
27 
28 impl From<SocketType> for U16<LittleEndian> {
from(socket_type: SocketType) -> Self29     fn from(socket_type: SocketType) -> Self {
30         (socket_type as u16).into()
31     }
32 }
33 
34 /// VirtioVsockConfig is the vsock device configuration space.
35 #[repr(C)]
36 pub struct VirtioVsockConfig {
37     /// The guest_cid field contains the guest’s context ID, which uniquely identifies
38     /// the device for its lifetime. The upper 32 bits of the CID are reserved and zeroed.
39     ///
40     /// According to virtio spec v1.1 2.4.1 Driver Requirements: Device Configuration Space,
41     /// drivers MUST NOT assume reads from fields greater than 32 bits wide are atomic.
42     /// So we need to split the u64 guest_cid into two parts.
43     pub guest_cid_low: ReadOnly<u32>,
44     pub guest_cid_high: ReadOnly<u32>,
45 }
46 
47 /// The message header for data packets sent on the tx/rx queues
48 #[repr(C, packed)]
49 #[derive(AsBytes, Clone, Copy, Debug, Eq, FromBytes, FromZeroes, PartialEq)]
50 pub struct VirtioVsockHdr {
51     pub src_cid: U64<LittleEndian>,
52     pub dst_cid: U64<LittleEndian>,
53     pub src_port: U32<LittleEndian>,
54     pub dst_port: U32<LittleEndian>,
55     pub len: U32<LittleEndian>,
56     pub socket_type: U16<LittleEndian>,
57     pub op: U16<LittleEndian>,
58     pub flags: U32<LittleEndian>,
59     /// Total receive buffer space for this socket. This includes both free and in-use buffers.
60     pub buf_alloc: U32<LittleEndian>,
61     /// Free-running bytes received counter.
62     pub fwd_cnt: U32<LittleEndian>,
63 }
64 
65 impl Default for VirtioVsockHdr {
default() -> Self66     fn default() -> Self {
67         Self {
68             src_cid: 0.into(),
69             dst_cid: 0.into(),
70             src_port: 0.into(),
71             dst_port: 0.into(),
72             len: 0.into(),
73             socket_type: SocketType::Stream.into(),
74             op: 0.into(),
75             flags: 0.into(),
76             buf_alloc: 0.into(),
77             fwd_cnt: 0.into(),
78         }
79     }
80 }
81 
82 impl VirtioVsockHdr {
83     /// Returns the length of the data.
len(&self) -> u3284     pub fn len(&self) -> u32 {
85         u32::from(self.len)
86     }
87 
op(&self) -> error::Result<VirtioVsockOp>88     pub fn op(&self) -> error::Result<VirtioVsockOp> {
89         self.op.try_into()
90     }
91 
source(&self) -> VsockAddr92     pub fn source(&self) -> VsockAddr {
93         VsockAddr {
94             cid: self.src_cid.get(),
95             port: self.src_port.get(),
96         }
97     }
98 
destination(&self) -> VsockAddr99     pub fn destination(&self) -> VsockAddr {
100         VsockAddr {
101             cid: self.dst_cid.get(),
102             port: self.dst_port.get(),
103         }
104     }
105 
check_data_is_empty(&self) -> error::Result<()>106     pub fn check_data_is_empty(&self) -> error::Result<()> {
107         if self.len() == 0 {
108             Ok(())
109         } else {
110             Err(SocketError::UnexpectedDataInPacket)
111         }
112     }
113 }
114 
115 /// Socket address.
116 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
117 pub struct VsockAddr {
118     /// Context Identifier.
119     pub cid: u64,
120     /// Port number.
121     pub port: u32,
122 }
123 
124 /// An event sent to the event queue
125 #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes, FromZeroes)]
126 #[repr(C)]
127 pub struct VirtioVsockEvent {
128     // ID from the virtio_vsock_event_id struct in the virtio spec
129     pub id: U32<LittleEndian>,
130 }
131 
132 #[derive(Copy, Clone, Eq, PartialEq)]
133 #[repr(u16)]
134 pub enum VirtioVsockOp {
135     Invalid = 0,
136 
137     /* Connect operations */
138     Request = 1,
139     Response = 2,
140     Rst = 3,
141     Shutdown = 4,
142 
143     /* To send payload */
144     Rw = 5,
145 
146     /* Tell the peer our credit info */
147     CreditUpdate = 6,
148     /* Request the peer to send the credit info to us */
149     CreditRequest = 7,
150 }
151 
152 impl From<VirtioVsockOp> for U16<LittleEndian> {
from(op: VirtioVsockOp) -> Self153     fn from(op: VirtioVsockOp) -> Self {
154         (op as u16).into()
155     }
156 }
157 
158 impl TryFrom<U16<LittleEndian>> for VirtioVsockOp {
159     type Error = SocketError;
160 
try_from(v: U16<LittleEndian>) -> Result<Self, Self::Error>161     fn try_from(v: U16<LittleEndian>) -> Result<Self, Self::Error> {
162         let op = match u16::from(v) {
163             0 => Self::Invalid,
164             1 => Self::Request,
165             2 => Self::Response,
166             3 => Self::Rst,
167             4 => Self::Shutdown,
168             5 => Self::Rw,
169             6 => Self::CreditUpdate,
170             7 => Self::CreditRequest,
171             _ => return Err(SocketError::UnknownOperation(v.into())),
172         };
173         Ok(op)
174     }
175 }
176 
177 impl fmt::Debug for VirtioVsockOp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result178     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179         match self {
180             Self::Invalid => write!(f, "VIRTIO_VSOCK_OP_INVALID"),
181             Self::Request => write!(f, "VIRTIO_VSOCK_OP_REQUEST"),
182             Self::Response => write!(f, "VIRTIO_VSOCK_OP_RESPONSE"),
183             Self::Rst => write!(f, "VIRTIO_VSOCK_OP_RST"),
184             Self::Shutdown => write!(f, "VIRTIO_VSOCK_OP_SHUTDOWN"),
185             Self::Rw => write!(f, "VIRTIO_VSOCK_OP_RW"),
186             Self::CreditUpdate => write!(f, "VIRTIO_VSOCK_OP_CREDIT_UPDATE"),
187             Self::CreditRequest => write!(f, "VIRTIO_VSOCK_OP_CREDIT_REQUEST"),
188         }
189     }
190 }
191 
192 bitflags! {
193     #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
194     pub(crate) struct Feature: u64 {
195         /// stream socket type is supported.
196         const STREAM = 1 << 0;
197         /// seqpacket socket type is supported.
198         const SEQ_PACKET = 1 << 1;
199 
200         // device independent
201         const NOTIFY_ON_EMPTY       = 1 << 24; // legacy
202         const ANY_LAYOUT            = 1 << 27; // legacy
203         const RING_INDIRECT_DESC    = 1 << 28;
204         const RING_EVENT_IDX        = 1 << 29;
205         const UNUSED                = 1 << 30; // legacy
206         const VERSION_1             = 1 << 32; // detect legacy
207 
208         // since virtio v1.1
209         const ACCESS_PLATFORM       = 1 << 33;
210         const RING_PACKED           = 1 << 34;
211         const IN_ORDER              = 1 << 35;
212         const ORDER_PLATFORM        = 1 << 36;
213         const SR_IOV                = 1 << 37;
214         const NOTIFICATION_DATA     = 1 << 38;
215     }
216 }
217 
218 bitflags! {
219     /// Flags sent with a shutdown request to hint that the peer won't send or receive more data.
220     #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
221     pub struct StreamShutdown: u32 {
222         /// The peer will not receive any more data.
223         const RECEIVE = 1 << 0;
224         /// The peer will not send any more data.
225         const SEND = 1 << 1;
226     }
227 }
228 
229 impl From<StreamShutdown> for U32<LittleEndian> {
from(flags: StreamShutdown) -> Self230     fn from(flags: StreamShutdown) -> Self {
231         flags.bits().into()
232     }
233 }
234