-
Notifications
You must be signed in to change notification settings - Fork 24
feat: vsock #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: vsock #12
Changes from 3 commits
1783861
f8d9567
767f529
1225728
b76d260
95afee9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| use axdriver_base::{BaseDriverOps, DevResult, DeviceType}; | ||
| use axdriver_vsock::{VsockConnId, VsockDriverEvent, VsockDriverOps}; | ||
| use virtio_drivers::{ | ||
| Hal, | ||
| device::socket::{ | ||
| VirtIOSocket, VsockAddr, VsockConnectionManager as InnerDev, VsockEvent, VsockEventType, | ||
| }, | ||
| transport::Transport, | ||
| }; | ||
|
|
||
| use crate::as_dev_err; | ||
|
|
||
| /// The VirtIO socket device driver. | ||
| pub struct VirtIoSocketDev<H: Hal, T: Transport> { | ||
| inner: InnerDev<H, T>, | ||
| } | ||
|
|
||
| unsafe impl<H: Hal, T: Transport> Send for VirtIoSocketDev<H, T> {} | ||
| unsafe impl<H: Hal, T: Transport> Sync for VirtIoSocketDev<H, T> {} | ||
|
|
||
| impl<H: Hal, T: Transport> VirtIoSocketDev<H, T> { | ||
| /// Creates a new driver instance and initializes the device, or returns | ||
| /// an error if any step fails. | ||
| pub fn try_new(transport: T) -> DevResult<Self> { | ||
| let virtio_socket = VirtIOSocket::<H, _>::new(transport).map_err(as_dev_err)?; | ||
| Ok(Self { | ||
| inner: InnerDev::new(virtio_socket), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl<H: Hal, T: Transport> BaseDriverOps for VirtIoSocketDev<H, T> { | ||
| fn device_name(&self) -> &str { | ||
| "virtio-socket" | ||
| } | ||
|
|
||
| fn device_type(&self) -> DeviceType { | ||
| DeviceType::Vsock | ||
| } | ||
| } | ||
|
|
||
| fn map_conn_id(cid: VsockConnId) -> (VsockAddr, u32) { | ||
| ( | ||
| VsockAddr { | ||
| cid: cid.peer_addr.cid as _, | ||
| port: cid.peer_addr.port as _, | ||
| }, | ||
| cid.local_port, | ||
| ) | ||
| } | ||
|
|
||
| impl<H: Hal, T: Transport> VsockDriverOps for VirtIoSocketDev<H, T> { | ||
| fn guest_cid(&self) -> u64 { | ||
| self.inner.guest_cid() | ||
| } | ||
|
|
||
| fn listen(&mut self, src_port: u32) { | ||
| self.inner.listen(src_port) | ||
| } | ||
|
|
||
| fn connect(&mut self, cid: VsockConnId) -> DevResult<()> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| self.inner.connect(peer_addr, src_port).map_err(as_dev_err) | ||
| } | ||
|
|
||
| fn send(&mut self, cid: VsockConnId, buf: &[u8]) -> DevResult<usize> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| match self.inner.send(peer_addr, src_port, buf) { | ||
| Ok(()) => Ok(buf.len()), | ||
| Err(e) => Err(as_dev_err(e)), | ||
| } | ||
| } | ||
|
|
||
| fn recv(&mut self, cid: VsockConnId, buf: &mut [u8]) -> DevResult<usize> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| self.inner | ||
| .recv(peer_addr, src_port, buf) | ||
| .map_err(as_dev_err) | ||
| } | ||
|
|
||
| fn recv_avail(&mut self, cid: VsockConnId) -> DevResult<usize> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| self.inner | ||
| .recv_buffer_available_bytes(peer_addr, src_port) | ||
| .map_err(as_dev_err) | ||
| } | ||
|
|
||
| fn disconnect(&mut self, cid: VsockConnId) -> DevResult<()> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| self.inner.shutdown(peer_addr, src_port).map_err(as_dev_err) | ||
| } | ||
|
|
||
| fn abort(&mut self, cid: VsockConnId) -> DevResult<()> { | ||
| let (peer_addr, src_port) = map_conn_id(cid); | ||
| self.inner | ||
| .force_close(peer_addr, src_port) | ||
| .map_err(as_dev_err) | ||
| } | ||
|
|
||
| fn poll_event(&mut self, buf: &mut [u8]) -> DevResult<Option<VsockDriverEvent>> { | ||
| match self.inner.poll() { | ||
| Ok(None) => { | ||
| // no event | ||
| Ok(None) | ||
| } | ||
| Ok(Some(event)) => { | ||
| // translate event | ||
| let result = convert_vsock_event(event, &mut self.inner, buf)?; | ||
| Ok(Some(result)) | ||
| } | ||
| Err(e) => { | ||
| // error | ||
| Err(as_dev_err(e)) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| fn convert_vsock_event<H: Hal, T: Transport>( | ||
| event: VsockEvent, | ||
| inner: &mut InnerDev<H, T>, | ||
| buf: &mut [u8], | ||
| ) -> DevResult<VsockDriverEvent> { | ||
| let cid = VsockConnId { | ||
| peer_addr: axdriver_vsock::VsockAddr { | ||
| cid: event.source.cid as _, | ||
| port: event.source.port as _, | ||
| }, | ||
| local_port: event.destination.port, | ||
| }; | ||
|
|
||
| match event.event_type { | ||
| VsockEventType::ConnectionRequest => Ok(VsockDriverEvent::ConnectionRequest(cid)), | ||
| VsockEventType::Connected => Ok(VsockDriverEvent::Connected(cid)), | ||
| VsockEventType::Received { length } => { | ||
| let read = inner | ||
| .recv(event.source, event.destination.port, &mut buf[..length]) | ||
eternalcomet marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| .map_err(as_dev_err)?; | ||
| Ok(VsockDriverEvent::Received(cid, read)) | ||
| } | ||
| VsockEventType::Disconnected { reason: _ } => Ok(VsockDriverEvent::Disconnected(cid)), | ||
| _ => Ok(VsockDriverEvent::Unknown), | ||
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| [package] | ||
| name = "axdriver_vsock" | ||
| edition.workspace = true | ||
| description = "Common traits and types for vsock drivers" | ||
| documentation = "https://arceos-org.github.io/axdriver_crates/axdriver_vsock" | ||
| keywords = ["arceos", "driver", "vsock"] | ||
| version.workspace = true | ||
| authors = ["Weikang Guo <guoweikang@kylinos.cn>"] | ||
| license.workspace = true | ||
| homepage.workspace = true | ||
| repository.workspace = true | ||
| categories.workspace = true | ||
|
|
||
| [features] | ||
| default = [] | ||
|
|
||
| [dependencies] | ||
| axdriver_base = { workspace = true } | ||
| log = "0.4" | ||
eternalcomet marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,84 @@ | ||||||||||||||||||||||||||
| //! Common traits and types for socket communite device drivers (i.e. disk). | ||||||||||||||||||||||||||
eternalcomet marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #![no_std] | ||||||||||||||||||||||||||
| #![cfg_attr(doc, feature(doc_cfg))] | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[doc(no_inline)] | ||||||||||||||||||||||||||
| pub use axdriver_base::{BaseDriverOps, DevError, DevResult, DeviceType}; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Vsock address. | ||||||||||||||||||||||||||
| #[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||||||||||||||||||||||||
| pub struct VsockAddr { | ||||||||||||||||||||||||||
| /// Context Identifier. | ||||||||||||||||||||||||||
| pub cid: u64, | ||||||||||||||||||||||||||
| /// Port number. | ||||||||||||||||||||||||||
| pub port: u32, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Vsock connection id. | ||||||||||||||||||||||||||
| #[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||||||||||||||||||||||||
| pub struct VsockConnId { | ||||||||||||||||||||||||||
| /// Peer address. | ||||||||||||||||||||||||||
| pub peer_addr: VsockAddr, | ||||||||||||||||||||||||||
| /// Local port. | ||||||||||||||||||||||||||
| pub local_port: u32, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| impl VsockConnId { | ||||||||||||||||||||||||||
| /// Create a new [`VsockConnId`] for listening socket | ||||||||||||||||||||||||||
| pub fn listening(local_port: u32) -> Self { | ||||||||||||||||||||||||||
| Self { | ||||||||||||||||||||||||||
| peer_addr: VsockAddr { cid: 0, port: 0 }, | ||||||||||||||||||||||||||
| local_port, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// VsockDriverEvent | ||||||||||||||||||||||||||
| #[derive(Debug)] | ||||||||||||||||||||||||||
| pub enum VsockDriverEvent { | ||||||||||||||||||||||||||
| /// ConnectionRequest | ||||||||||||||||||||||||||
| ConnectionRequest(VsockConnId), | ||||||||||||||||||||||||||
| /// Connected | ||||||||||||||||||||||||||
| Connected(VsockConnId), | ||||||||||||||||||||||||||
| /// Received | ||||||||||||||||||||||||||
| Received(VsockConnId, usize), | ||||||||||||||||||||||||||
| /// Disconnected | ||||||||||||||||||||||||||
| Disconnected(VsockConnId), | ||||||||||||||||||||||||||
| /// unknown event | ||||||||||||||||||||||||||
eternalcomet marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
| Unknown, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Operations that require a block storage device driver to implement. | ||||||||||||||||||||||||||
eternalcomet marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
| pub trait VsockDriverOps: BaseDriverOps { | ||||||||||||||||||||||||||
| /// guest cid | ||||||||||||||||||||||||||
| fn guest_cid(&self) -> u64; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Listen on a specific port. | ||||||||||||||||||||||||||
| fn listen(&mut self, src_port: u32); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Connect to a peer socket. | ||||||||||||||||||||||||||
| fn connect(&mut self, cid: VsockConnId) -> DevResult<()>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Send data to the connected peer socket. need addr for DGRAM mode | ||||||||||||||||||||||||||
| fn send(&mut self, cid: VsockConnId, buf: &[u8]) -> DevResult<usize>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Receive data from the connected peer socket. | ||||||||||||||||||||||||||
| fn recv(&mut self, cid: VsockConnId, buf: &mut [u8]) -> DevResult<usize>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Returns the number of bytes in the receive buffer available to be read | ||||||||||||||||||||||||||
| /// by recv. | ||||||||||||||||||||||||||
| fn recv_avail(&mut self, cid: VsockConnId) -> DevResult<usize>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Disconnect from the connected peer socket. | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Requests to shut down the connection cleanly, telling the peer that we | ||||||||||||||||||||||||||
| /// won't send or receive any more data. | ||||||||||||||||||||||||||
| fn disconnect(&mut self, cid: VsockConnId) -> DevResult<()>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Forcibly closes the connection without waiting for the peer. | ||||||||||||||||||||||||||
| fn abort(&mut self, cid: VsockConnId) -> DevResult<()>; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// poll event from driver | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| /// poll event from driver | |
| /// Poll a single event from the driver. | |
| /// | |
| /// The caller provides `buf` as a scratch buffer that implementations may use | |
| /// to decode or temporarily store driver-specific data associated with the | |
| /// returned [`VsockDriverEvent`]. The buffer is typically only used when an | |
| /// event is actually available (`Ok(Some(event))`) and may be ignored when | |
| /// there is no event (`Ok(None)`) or when an error is returned. | |
| /// | |
| /// Implementations must not rely on the contents of `buf` on entry, and | |
| /// callers should ensure it is large enough for any driver-specific payload | |
| /// they expect to handle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import of
SocketError::*may cause namespace pollution since it brings all socket error variants into scope. This could lead to naming conflicts if other error types have similar variant names. Consider using qualified paths likedevice::socket::SocketError::ConnectionExistsin the match arms instead, or limiting the wildcard import scope.