Skip to content
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

add support of a virtio socket device #826

Merged
merged 18 commits into from
Aug 22, 2024
Merged

Conversation

stlankes
Copy link
Contributor

@stlankes stlankes commented Aug 7, 2023

The current interface is able to work as server. System calls like bind, listen, accept and connect are supported.

The hermit-os/hermit-rs#450 is an example to use the interface.

@egrimley-arm
Copy link
Contributor

I'm interested in testing this, but what will be the way to access vsock from the application?

@stlankes
Copy link
Contributor Author

It isn't finished and in the beginning. At the end it should work like https://gist.github.com/mcastelino/9a57d00ccf245b98de2129f0efe39857

@stlankes stlankes force-pushed the vsock branch 22 times, most recently from 442cdc4 to 77a0ff7 Compare July 25, 2024 18:05
@stlankes stlankes marked this pull request as ready for review August 6, 2024 19:49
@stlankes stlankes changed the title add draft of a vsock driver add support of a virtio socket device Aug 6, 2024
@stlankes stlankes requested review from cagatay-y and mkroening August 6, 2024 20:33
@stlankes
Copy link
Contributor Author

stlankes commented Aug 8, 2024

@mkroening The CI error doesn't depend to this PR

@mkroening
Copy link
Member

mkroening commented Aug 8, 2024

@mkroening The CI error doesn't depend to this PR

Yes, thats rust-lang/rust#128808. It should be resolved tomorrow.

After accepting a connection, the new socket has to use
the same port like the listening stream.

=> Accepting of new connection is not possible.
Copy link
Member

@mkroening mkroening left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@cagatay-y will take a look at the virtqueue-related bits.

Is this ready to merge from your side, @stlankes? Should I squash some commits before merging? :)

src/executor/vsock.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
#[cfg(not(target_arch = "riscv64"))]
add_irq_name(irq_no, "virtio_net");
add_irq_name(irq_no, "virtio");
let _ = VIRTIO_IRQ.try_insert(irq_no);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let _ = VIRTIO_IRQ.try_insert(irq_no);
if let Err((final_value, _)) = VIRTIO_IRQ.try_insert(irq_no) {
assert_eq!(*final_value, irq_no);
}

irq_install_handler(irq_no, virtio_irqhandler);
#[cfg(not(target_arch = "riscv64"))]
add_irq_name(irq_no, "virtio");
let _ = VIRTIO_IRQ.try_insert(irq_no);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let _ = VIRTIO_IRQ.try_insert(irq_no);
if let Err((final_value, _)) = VIRTIO_IRQ.try_insert(irq_no) {
assert_eq!(*final_value, irq_no);
}

use crate::drivers::virtio::transport::VIRTIO_IRQ;

let irq = device.get_irq().unwrap();
let _ = VIRTIO_IRQ.try_insert(irq);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let _ = VIRTIO_IRQ.try_insert(irq);
if let Err((final_value, _)) = VIRTIO_IRQ.try_insert(irq_no) {
assert_eq!(*final_value, irq_no);
}

let irq = device.get_irq().unwrap();
let _ = VIRTIO_IRQ.try_insert(irq);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let _ = VIRTIO_IRQ.try_insert(irq);
if let Err((final_value, _)) = VIRTIO_IRQ.try_insert(irq_no) {
assert_eq!(*final_value, irq_no);
}

@mkroening mkroening added this pull request to the merge queue Aug 22, 2024
Merged via the queue into hermit-os:main with commit 6dac572 Aug 22, 2024
13 checks passed
fn add(&mut self, mut vq: Box<dyn Virtq>) {
const BUFF_PER_PACKET: u16 = 2;
let num_packets: u16 = u16::from(vq.size()) / BUFF_PER_PACKET;
fill_queue(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do device events have headers? If not, fill_queue cannot be reused for EventQueue, since it allocates and puts before the payload a header structure. Also, if the function is adapted for the EventQueue use case, num_packets will not need to be divided by two since the buffers in the queue will consist of a single element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EventQueue is currently a dummy queue. The standard want that we register such a queue. For instance, a migration signal can be sent to the kernel. Currently, we don't support it. => Just a dummy registration.

vq: None,
poll_sender,
poll_receiver,
packet_size: crate::VSOCK_PACKET_SIZE + mem::size_of::<Hdr>() as u32,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packet_size does not need to include the header size since fill_queue allocates the header separately and uses the packet_size parameter only for the payload vector.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will fix it.

pub fn handle_interrupt(&mut self) {
let _ = self.isr_stat.is_interrupt();

if self.isr_stat.is_cfg_change() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the way we currently handle IsrStatus for PCIe transport is incorrect. The specification says that "To avoid an extra access, simply reading this register resets it to 0 and causes the device to de-assert the interrupt" (v1.2 § 4.1.4.5), so the is_interrupt read may be resetting the status and cause the is_cfg_change to always return false. I think it should be fixed in the IsrStatus impl but I couldn't write a review comment for an unchanged line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will revise it.

}

pub fn handle_interrupt(&mut self) {
let _ = self.isr_stat.is_interrupt();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rename is_interrupt to something like is_queue_interrupt to clarify that it does not check for configuration change interrupts and is specific to used buffer interrupts. It would also match the naming used in the specification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I will do it.

let handle = nic.create_udp_handle().unwrap();
drop(guard);
let socket = udp::Socket::new(handle);
#[cfg(feature = "vsock")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we have a match on domain here? It seems to me that if "vsock" is enabled, the function will always early return a socket regardless of domain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I will fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants