virtio_drivers/device/socket/
protocol.rs1use super::error::{self, SocketError};
4use crate::config::ReadOnly;
5use bitflags::bitflags;
6use core::{
7 convert::{TryFrom, TryInto},
8 fmt,
9};
10use zerocopy::{
11 byteorder::{LittleEndian, U16, U32, U64},
12 FromBytes, Immutable, IntoBytes, KnownLayout,
13};
14
15pub const VMADDR_CID_HOST: u64 = 2;
17
18#[derive(Copy, Clone, Debug)]
20#[repr(u16)]
21pub enum SocketType {
22 Stream = 1,
24 SeqPacket = 2,
26}
27
28impl From<SocketType> for U16<LittleEndian> {
29 fn from(socket_type: SocketType) -> Self {
30 (socket_type as u16).into()
31 }
32}
33
34#[derive(FromBytes, Immutable, IntoBytes)]
36#[repr(C)]
37pub struct VirtioVsockConfig {
38 pub guest_cid_low: ReadOnly<u32>,
45 pub guest_cid_high: ReadOnly<u32>,
46}
47
48#[repr(C, packed)]
50#[derive(Clone, Copy, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
51pub struct VirtioVsockHdr {
52 pub src_cid: U64<LittleEndian>,
53 pub dst_cid: U64<LittleEndian>,
54 pub src_port: U32<LittleEndian>,
55 pub dst_port: U32<LittleEndian>,
56 pub len: U32<LittleEndian>,
57 pub socket_type: U16<LittleEndian>,
58 pub op: U16<LittleEndian>,
59 pub flags: U32<LittleEndian>,
60 pub buf_alloc: U32<LittleEndian>,
62 pub fwd_cnt: U32<LittleEndian>,
64}
65
66impl Default for VirtioVsockHdr {
67 fn default() -> Self {
68 Self {
69 src_cid: 0.into(),
70 dst_cid: 0.into(),
71 src_port: 0.into(),
72 dst_port: 0.into(),
73 len: 0.into(),
74 socket_type: SocketType::Stream.into(),
75 op: 0.into(),
76 flags: 0.into(),
77 buf_alloc: 0.into(),
78 fwd_cnt: 0.into(),
79 }
80 }
81}
82
83impl VirtioVsockHdr {
84 pub fn len(&self) -> u32 {
86 u32::from(self.len)
87 }
88
89 pub fn op(&self) -> error::Result<VirtioVsockOp> {
90 self.op.try_into()
91 }
92
93 pub fn source(&self) -> VsockAddr {
94 VsockAddr {
95 cid: self.src_cid.get(),
96 port: self.src_port.get(),
97 }
98 }
99
100 pub fn destination(&self) -> VsockAddr {
101 VsockAddr {
102 cid: self.dst_cid.get(),
103 port: self.dst_port.get(),
104 }
105 }
106
107 pub fn check_data_is_empty(&self) -> error::Result<()> {
108 if self.len() == 0 {
109 Ok(())
110 } else {
111 Err(SocketError::UnexpectedDataInPacket)
112 }
113 }
114}
115
116#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
118pub struct VsockAddr {
119 pub cid: u64,
121 pub port: u32,
123}
124
125#[derive(Copy, Clone, Debug, Default, IntoBytes, FromBytes, Immutable, KnownLayout)]
127#[repr(C)]
128pub struct VirtioVsockEvent {
129 pub id: U32<LittleEndian>,
131}
132
133#[derive(Copy, Clone, Eq, PartialEq)]
134#[repr(u16)]
135pub enum VirtioVsockOp {
136 Invalid = 0,
137
138 Request = 1,
140 Response = 2,
141 Rst = 3,
142 Shutdown = 4,
143
144 Rw = 5,
146
147 CreditUpdate = 6,
149 CreditRequest = 7,
151}
152
153impl From<VirtioVsockOp> for U16<LittleEndian> {
154 fn from(op: VirtioVsockOp) -> Self {
155 (op as u16).into()
156 }
157}
158
159impl TryFrom<U16<LittleEndian>> for VirtioVsockOp {
160 type Error = SocketError;
161
162 fn try_from(v: U16<LittleEndian>) -> Result<Self, Self::Error> {
163 let op = match u16::from(v) {
164 0 => Self::Invalid,
165 1 => Self::Request,
166 2 => Self::Response,
167 3 => Self::Rst,
168 4 => Self::Shutdown,
169 5 => Self::Rw,
170 6 => Self::CreditUpdate,
171 7 => Self::CreditRequest,
172 _ => return Err(SocketError::UnknownOperation(v.into())),
173 };
174 Ok(op)
175 }
176}
177
178impl fmt::Debug for VirtioVsockOp {
179 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180 match self {
181 Self::Invalid => write!(f, "VIRTIO_VSOCK_OP_INVALID"),
182 Self::Request => write!(f, "VIRTIO_VSOCK_OP_REQUEST"),
183 Self::Response => write!(f, "VIRTIO_VSOCK_OP_RESPONSE"),
184 Self::Rst => write!(f, "VIRTIO_VSOCK_OP_RST"),
185 Self::Shutdown => write!(f, "VIRTIO_VSOCK_OP_SHUTDOWN"),
186 Self::Rw => write!(f, "VIRTIO_VSOCK_OP_RW"),
187 Self::CreditUpdate => write!(f, "VIRTIO_VSOCK_OP_CREDIT_UPDATE"),
188 Self::CreditRequest => write!(f, "VIRTIO_VSOCK_OP_CREDIT_REQUEST"),
189 }
190 }
191}
192
193bitflags! {
194 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
195 pub(crate) struct Feature: u64 {
196 const STREAM = 1 << 0;
198 const SEQ_PACKET = 1 << 1;
200
201 const NOTIFY_ON_EMPTY = 1 << 24; const ANY_LAYOUT = 1 << 27; const RING_INDIRECT_DESC = 1 << 28;
205 const RING_EVENT_IDX = 1 << 29;
206 const UNUSED = 1 << 30; const VERSION_1 = 1 << 32; const ACCESS_PLATFORM = 1 << 33;
211 const RING_PACKED = 1 << 34;
212 const IN_ORDER = 1 << 35;
213 const ORDER_PLATFORM = 1 << 36;
214 const SR_IOV = 1 << 37;
215 const NOTIFICATION_DATA = 1 << 38;
216 }
217}
218
219bitflags! {
220 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
222 pub struct StreamShutdown: u32 {
223 const RECEIVE = 1 << 0;
225 const SEND = 1 << 1;
227 }
228}
229
230impl From<StreamShutdown> for U32<LittleEndian> {
231 fn from(flags: StreamShutdown) -> Self {
232 flags.bits().into()
233 }
234}