Skip to content

Commit fa3e7d6

Browse files
hikejsclaude
andcommitted
docs(vsock): add DGRAM implementation documentation
Document the architecture, implementation details, and design decisions for virtio-vsock DGRAM support on Windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e7700cc commit fa3e7d6

1 file changed

Lines changed: 168 additions & 0 deletions

File tree

docs/vsock-dgram-implementation.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# Virtio-vsock DGRAM Implementation on Windows
2+
3+
## Overview
4+
5+
This document describes the implementation of DGRAM (datagram/connectionless) support for virtio-vsock on Windows, completing the P2 feature set for the Windows backend.
6+
7+
## Background
8+
9+
Virtio-vsock supports two socket types:
10+
- **STREAM (type 1)**: Connection-oriented, reliable, ordered (like TCP)
11+
- **DGRAM (type 3)**: Connectionless, unreliable, unordered (like UDP)
12+
13+
Prior to this implementation, the Windows backend only supported STREAM sockets via TCP and Named Pipes. DGRAM support enables connectionless communication scenarios.
14+
15+
## Architecture
16+
17+
### Data Structures
18+
19+
```rust
20+
pub struct Vsock {
21+
// ... existing fields ...
22+
streams: HashMap<u32, StreamState>, // STREAM sockets
23+
dgram_sockets: HashMap<u32, UdpSocket>, // DGRAM sockets (NEW)
24+
// ... other fields ...
25+
}
26+
```
27+
28+
### Key Components
29+
30+
1. **DGRAM Socket Management**
31+
- `dgram_sockets: HashMap<u32, UdpSocket>` maps guest port → UDP socket
32+
- Sockets are created on-demand when first DGRAM packet is sent
33+
- Each socket is bound to `0.0.0.0:0` (any local address/port)
34+
35+
2. **TX Path (Guest → Host)**
36+
- Guest sends DGRAM packet via `VSOCK_OP_RW` with `VSOCK_TYPE_DGRAM`
37+
- VMM creates UDP socket if not exists
38+
- VMM sends datagram to mapped host port via `UdpSocket::send_to()`
39+
40+
3. **RX Path (Host → Guest)**
41+
- `harvest_dgram_reads()` polls all DGRAM sockets
42+
- Receives datagrams via `UdpSocket::recv_from()`
43+
- Constructs vsock header with `VSOCK_TYPE_DGRAM`
44+
- Queues packet to guest RX queue
45+
46+
## Implementation Details
47+
48+
### Feature Advertisement
49+
50+
```rust
51+
const AVAIL_FEATURES: u64 = (1 << VIRTIO_F_VERSION_1 as u64)
52+
| (1 << VIRTIO_F_IN_ORDER as u64)
53+
| (1 << VIRTIO_VSOCK_F_DGRAM as u64); // Bit 3
54+
```
55+
56+
### TX Processing (VSOCK_OP_RW)
57+
58+
```rust
59+
if pkt_type == VSOCK_TYPE_DGRAM {
60+
// Create socket on first use
61+
if !self.dgram_sockets.contains_key(&src_port) {
62+
let socket = UdpSocket::bind("0.0.0.0:0")?;
63+
socket.set_nonblocking(true)?;
64+
self.dgram_sockets.insert(src_port, socket);
65+
}
66+
67+
// Send datagram to host
68+
if let Some(socket) = self.dgram_sockets.get(&src_port) {
69+
if let Some(addr) = self.host_socket_addr(dst_port) {
70+
socket.send_to(&payload, addr)?;
71+
}
72+
}
73+
}
74+
```
75+
76+
### RX Processing (harvest_dgram_reads)
77+
78+
```rust
79+
fn harvest_dgram_reads(&mut self) {
80+
for (guest_port, socket) in &self.dgram_sockets {
81+
let mut rx_buf = [0u8; 4096];
82+
match socket.recv_from(&mut rx_buf) {
83+
Ok((n, peer_addr)) => {
84+
// Construct vsock header
85+
let mut hdr = [0u8; 44];
86+
Self::set_u64(&mut hdr, 0, VSOCK_HOST_CID);
87+
Self::set_u64(&mut hdr, 8, self.cid);
88+
Self::set_u32(&mut hdr, 16, peer_addr.port() as u32);
89+
Self::set_u32(&mut hdr, 20, guest_port);
90+
Self::set_u32(&mut hdr, 24, n as u32);
91+
Self::set_u16(&mut hdr, 28, VSOCK_TYPE_DGRAM);
92+
Self::set_u16(&mut hdr, 30, VSOCK_OP_RW);
93+
94+
self.queue_response(&hdr, VSOCK_OP_RW, rx_buf[..n].to_vec());
95+
}
96+
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {}
97+
Err(_) => {}
98+
}
99+
}
100+
}
101+
```
102+
103+
## Differences from STREAM
104+
105+
| Aspect | STREAM | DGRAM |
106+
|--------|--------|-------|
107+
| Connection | Requires REQUEST/RESPONSE handshake | No handshake |
108+
| State | Maintains StreamState per connection | Stateless (socket per port) |
109+
| Flow Control | Credit-based (buf_alloc, fwd_cnt, tx_cnt) | None |
110+
| Backend | TCP or Named Pipe | UDP |
111+
| Reliability | Guaranteed delivery, ordered | Best-effort, may be lost/reordered |
112+
| Operations | REQUEST, RESPONSE, RW, CREDIT_UPDATE, SHUTDOWN, RST | RW only |
113+
114+
## Testing
115+
116+
### Smoke Test
117+
118+
```rust
119+
#[test]
120+
fn test_whpx_vsock_dgram_feature() {
121+
let vsock = Vsock::new(3, None, None, Default::default()).unwrap();
122+
123+
// Verify DGRAM feature is advertised
124+
let features = vsock.avail_features();
125+
assert_ne!(features & (1 << 3), 0, "VIRTIO_VSOCK_F_DGRAM not advertised");
126+
}
127+
```
128+
129+
### Test Results
130+
131+
```
132+
running 54 tests
133+
test windows::vstate::tests::test_whpx_vsock_dgram_feature ... ok
134+
test windows::vstate::tests::test_whpx_vsock_init_smoke ... ok
135+
test windows::vstate::tests::test_whpx_vsock_tx_smoke ... ok
136+
test result: ok. 44 passed; 0 failed; 10 ignored; 0 measured
137+
```
138+
139+
## Limitations
140+
141+
1. **Port Mapping Heuristic**: RX path uses peer UDP port as guest dst_port. This may not match the original guest port if NAT is involved.
142+
143+
2. **No Reverse Mapping**: The implementation doesn't maintain a reverse mapping from host UDP ports to guest ports, which could cause issues in complex scenarios.
144+
145+
3. **UDP Only**: DGRAM support is limited to UDP. Named Pipe DGRAM is not implemented (Windows Named Pipes don't support datagram mode).
146+
147+
4. **No Fragmentation**: Large datagrams (>4096 bytes) are not supported. UDP fragmentation is handled by the network stack.
148+
149+
## Future Improvements
150+
151+
1. **Port Mapping Table**: Maintain bidirectional mapping between guest ports and host UDP ports for accurate RX routing.
152+
153+
2. **Socket Cleanup**: Implement timeout-based cleanup for idle DGRAM sockets to prevent resource leaks.
154+
155+
3. **Error Handling**: Improve error handling for socket creation and I/O failures.
156+
157+
4. **Metrics**: Add counters for DGRAM packets sent/received, errors, etc.
158+
159+
## References
160+
161+
- [Virtio Specification - vsock Device](https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-4050008)
162+
- [Linux vsock DGRAM implementation](https://github.com/torvalds/linux/blob/master/net/vmw_vsock/af_vsock.c)
163+
- Windows UDP Socket API: `std::net::UdpSocket`
164+
165+
---
166+
167+
*Implementation Date: 2026-03-05*
168+
*Commit: e7700cc*

0 commit comments

Comments
 (0)