Skip to content

Commit

Permalink
Connect to gvproxy socket
Browse files Browse the repository at this point in the history
Connecting to the socket set the remote address so we can use
send()/recv() or write()/read() instead of sendto()/recvfrom().

Advantages:
- Simpler code, no need to keep the remote address.
- The server will want to connect to the client address to ensure it
  receives frames only from the connected client. Such server will want
  to remove the unix socket once the client connected[2], which doe snot
  work with current code.
- Once the socket is connected, the same backend can be used to handle
  passed file descriptor[1].
- iperf3 -R is 1.33 times faster (46.6 Gbits/s vs 35.0 Gbits/s).

Tested with:
- [x] gvproxy
- [x] vmnet-helper

For testing results see
#264 (comment)

[1] containers/krunkit#24
[2] https://github.com/nirs/vmnet-helper/blob/5c6a595ba3e76314e1d0bef2b0160388439d69ec/helper.c#L475

Signed-off-by: Nir Soffer <[email protected]>
  • Loading branch information
nirs committed Feb 6, 2025
1 parent 57a5a6b commit 8f8343b
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions src/devices/src/virtio/net/gvproxy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use nix::fcntl::{fcntl, FcntlArg, OFlag};
use nix::sys::socket::{
bind, getsockopt, recv, sendto, setsockopt, socket, sockopt, AddressFamily, MsgFlags, SockFlag,
SockType, UnixAddr,
bind, connect, getsockopt, recv, send, setsockopt, socket, sockopt, AddressFamily, MsgFlags,
SockFlag, SockType, UnixAddr,
};
use nix::unistd::unlink;
use std::os::fd::{AsRawFd, RawFd};
Expand All @@ -13,7 +13,6 @@ const VFKIT_MAGIC: [u8; 4] = *b"VFKT";

pub struct Gvproxy {
fd: RawFd,
peer_addr: UnixAddr,
}

impl Gvproxy {
Expand All @@ -34,8 +33,11 @@ impl Gvproxy {
}
bind(fd, &local_addr).map_err(ConnectError::Binding)?;

sendto(fd, &VFKIT_MAGIC, &peer_addr, MsgFlags::empty())
.map_err(ConnectError::SendingMagic)?;
// connect so we dn't need to use peer address again. This also allows the
// server to remove the socket after the connection.
connect(fd, &peer_addr).map_err(ConnectError::Binding)?;

send(fd, &VFKIT_MAGIC, MsgFlags::empty()).map_err(ConnectError::SendingMagic)?;

// macOS forces us to do this here instead of just using SockFlag::SOCK_NONBLOCK above.
match fcntl(fd, FcntlArg::F_GETFL) {
Expand Down Expand Up @@ -78,7 +80,7 @@ impl Gvproxy {
getsockopt(fd, sockopt::RcvBuf)
);

Ok(Self { fd, peer_addr })
Ok(Self { fd })
}
}

Expand Down Expand Up @@ -110,8 +112,8 @@ impl NetBackend for Gvproxy {
/// If this function returns WriteError::PartialWrite, you have to finish the write using
/// try_finish_write.
fn write_frame(&mut self, hdr_len: usize, buf: &mut [u8]) -> Result<(), WriteError> {
let ret = sendto(self.fd, &buf[hdr_len..], &self.peer_addr, MsgFlags::empty())
.map_err(WriteError::Internal)?;
let ret =
send(self.fd, &buf[hdr_len..], MsgFlags::empty()).map_err(WriteError::Internal)?;
debug!(
"Written frame size={}, written={}",
buf.len() - hdr_len,
Expand Down

0 comments on commit 8f8343b

Please sign in to comment.