firecracker icon indicating copy to clipboard operation
firecracker copied to clipboard

[Feature Request] Add SEQPACKET socket type for vsock

Open gabivlj opened this issue 1 year ago • 7 comments

Feature Request

https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html

VIRTIO_VSOCK_F_SEQPACKET has been introduced as an option for virtio vsock. It would enable the use-case of VMs that are relaying datagrams over a vsock and need to keep the boundaries without a SOCK_STREAM combining them together.

Right now you can connect from the VM opening a vsock with SOCK_STREAM type, but not with SOCK_SEQPACKET. This would also mean that on the host side the created UDS needs to match the socket type of the vsock.

Describe the desired solution

This should work:

	socketFd, err := unix.Socket(unix.AF_VSOCK, unix.SOCK_SEQPACKET, 0)
	if err != nil {
		return nil, 0, err
	}

	sockaddr := &unix.SockaddrVM{
		CID:  2,
		Port: 500,
	}
	if err := unix.Connect(socketFd, sockaddr); err != nil {
		return nil, 0, err
	}

And if the opened UDS on the host side doesn't match the sock type it should not go ahead with the connection.

Describe possible alternatives

I worked around this by implementing packet boundaries within the stream socket, but it's clearly a not very efficient solution and slow.

Checks

  • [x] Have you searched the Firecracker Issues database for similar requests?
  • [x] Have you read all the existing relevant Firecracker documentation?
  • [x] Have you read and understood Firecracker's core tenets?

I am curious if this is something the Firecracker team is interested in implementing for their vsock virtio component.

gabivlj avatar Sep 27 '24 16:09 gabivlj

Hi gabivlj, Thank you very much for your interest into Firecracker and this feature request. While at the moment we are not actively working to implement this feature, we are more than happy to receive contribution from the community to implement it. We will make sure to review any implementation of it. Thanks, Jack

JackThomson2 avatar Oct 15 '24 10:10 JackThomson2

I can pick this up, though I'm new to the project so may need some pointers

evanrittenhouse avatar Dec 29 '24 18:12 evanrittenhouse

Thanks @evanrittenhouse, our getting started guide here is probably the best place to get going. Any other pointers/questions feel free to reach out

JackThomson2 avatar Mar 19 '25 15:03 JackThomson2

@evanrittenhouse CC: @JackThomson2

I see if you were still interested in working on this issue. If not, would I be able to take it on? Thank you!

gjkeller avatar Apr 10 '25 20:04 gjkeller

I was looking at what it would take to add this over the past week and came up with some ideas:

  1. When the vsock device is started, the vmm opens a UDS at the configured uds_path on the host. Any host-initiated connections happen via this socket. Based on that, it seems like the socket type should be stated in the vsock device configuration alongside guest_cid and uds_path. This would mean the entire vsock device "has" a socket type, which is implicitly the behavior at the moment. (This isn't the only option: on vsock device start the vmm could open 2 UDSs on the host, one at ${uds_path}_stream and another at ${uds_path}_seqpacket and leave it up to the socket on the host-side which one it wants to connect() to. I'm not sure this is the way to go since probably only one socket would be used, leaving the other one sitting (a bit wasteful), and it adds the complexity of having to manage two different stream types at once within the vsock backend, which at the moment benefits from assuming only TYPE_STREAM). How does this sound from a design standpoint?
  2. stdlib doesn't have support for UDS of type SOCK_SEQPACKET (see here). A UnixSeqpacketListener or similar would have to be implemented from unsafe libc calls (or an existing implementation pulled in from somewhere). I assume this could live within the vsock module, since it doesn't seem like it would be used elsewhere.
  3. There is a slight incongruity between virtio vsock's seqpacket and UDS seqpacket. Virtio allows two boundary markers - end of message (VIRTIO_VSOCK_SEQ_EOM packet flag) and end of record (VIRTIO_VSOCK_SEQ_EOR packet flag) - while UDS only has the end of record flag. To me this means that multiple RW packets from the guest side, ending with a packet with the EOM flag set, must be sent to the host socket in one message. Going the other way, a single message from a host socket to the guest socket can be sent as a single message or multiple messages but the EOM flag must be set on the last message. An additional requirement of AF_UNIX SOCK_SEQPACKET is that each input system call (read(), recv(), etc) must consume an entire packet or the part that was not consumed will be dropped. These considerations would have to be mediated by VSockConnection.

Please let me know if I'm mistaken about anything!

TomRCummings avatar Apr 15 '25 16:04 TomRCummings

@gjkeller we don't have any progress on this. Feel free to work on it.

bchalios avatar Apr 16 '25 13:04 bchalios

Just a minor draft, very heavily a work in progress done in part with @gjkeller.

bstrong04 avatar May 07 '25 05:05 bstrong04