-
Notifications
You must be signed in to change notification settings - Fork 87
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
Conversation
I'm interested in testing this, but what will be the way to access vsock from the application? |
It isn't finished and in the beginning. At the end it should work like https://gist.github.com/mcastelino/9a57d00ccf245b98de2129f0efe39857 |
442cdc4
to
77a0ff7
Compare
@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.
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.
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? :)
#[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); |
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.
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); |
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.
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); |
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.
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); |
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.
let _ = VIRTIO_IRQ.try_insert(irq); | |
if let Err((final_value, _)) = VIRTIO_IRQ.try_insert(irq_no) { | |
assert_eq!(*final_value, irq_no); | |
} |
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( |
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.
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.
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 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, |
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.
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.
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.
Ok, I will fix it.
pub fn handle_interrupt(&mut self) { | ||
let _ = self.isr_stat.is_interrupt(); | ||
|
||
if self.isr_stat.is_cfg_change() { |
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.
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.
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.
Ok, I will revise it.
} | ||
|
||
pub fn handle_interrupt(&mut self) { | ||
let _ = self.isr_stat.is_interrupt(); |
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.
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.
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.
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")] |
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.
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
.
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.
You are right, I will fix it.
The current interface is able to work as server. System calls like
bind
,listen
,accept
andconnect
are supported.The hermit-os/hermit-rs#450 is an example to use the interface.