Repository navigation
viona: want F_EVENT_IDX support - #1171
Conversation
This adds F_EVENT_IDX support for all virtqueues, but for this commit we enable it for viona only. This is needed to support F_EVENT_IDX for the viona control queue, which is required so that the illumos viona device may offer it for the data queues. It was found that Tx completion interrupts are greatly reduced with this feature support, presumably due to the Linux driver's better use of `avail.used_event` for interrupt moderation.
|
I have only tested this with an Ubuntu Server 24.04 guest thus far. I'll see about trying to test some other platforms, but I don't have the slightest idea on testing Windows. |
FelixMcFelix
left a comment
There was a problem hiding this comment.
Thanks Ryan, Double checking some things to make sure I understand what's going on with the wrapping math 100%.
- remove eprintln - add probe for viona set_features - properly negotiate F_EVENT_IDX - undo API version bump, features shouldn't be tied to this number - tests shouldn't assume F_EVENT_IDX is or is-not enabled - remove Features::RING_EVENT_IDX, this feature should never be assumed to work across all devices and instead must be negotiated per-device
|
I have successfully tested this in propolis-standalone with the following guests:
For all of them I confirmed network connectivity for both an opte-based link used to test VPC traffic as it looks in an Oxide rack, as well as a non-opte VNIC link for external traffic. I use the external link to SSH to the guest and download software, and then I used the VPC link to run iperf3 tests between guests running on another host (to ensure that traffic leaves opte and hits vinoa/mac/cxgbe). Using in-guest tools and/or the new dtrace probe I also verified that F_EVENT_IDX is negotiated, as shown for windows below: Note that |
iximeow
left a comment
There was a problem hiding this comment.
I spent wayyyyy too long puzzling over the same math Kyle did but at least I think I see what we all are thinking and hopefully my words made sense there.
I'm +1 on this as-is iff the diff on VIONA_CURRENT_INTERFACE_VERSION really is because this is an old base (maybe merge master?). in as much as I've asked about changes, my comments are very easily followup that I'm happy to do if you want. but if so I'll tag you for review (and if you take a month in retribution, I understand 😔)
| #[cfg(target_os = "illumos")] | ||
|
|
||
| mod os { | ||
| unsafe extern "C" { | ||
| pub fn membar_enter(); | ||
| } | ||
| } | ||
|
|
||
| #[inline(always)] | ||
| pub fn membar_enter() { | ||
| #[cfg(target_os = "illumos")] | ||
| unsafe { | ||
| os::membar_enter(); | ||
| } | ||
| } |
There was a problem hiding this comment.
if you wanted to put this somewhere like lib/propolis/src/util/mod.rs that would probably be good. you may have been surprised that we don't have membar_enter anywhere in propolis to date and that's mostly because we've (mis)used std::sync::atomic::fence as a barrier. so if you don't move it here then I will later to use in the other places.
There was a problem hiding this comment.
because we've (mis)used std::sync::atomic::fence as a barrier
Yes. I forget the details, but basically I figured out that rust atomics are not sufficient as they will not, at runtime, invoke the host's membar_enter(), which is needed for correctness.
I started moving this for you and realized that I should leave it to you as you probably have stronger ideas on how you like things organized, and whether you like it or not I consider you the head custodian of this repo.
| /// against. All constants and structs defined by the crate are done so in | ||
| /// terms of that specific version. | ||
| pub const VIONA_CURRENT_INTERFACE_VERSION: u32 = 6; | ||
| pub const VIONA_CURRENT_INTERFACE_VERSION: u32 = 7; |
There was a problem hiding this comment.
I think this is only in the diff still because your base is older than the commit on master that also bumped VIONA_CURRENT_INTERFACE_VERSION?
| /// Return used_event value. | ||
| fn used_event(&self, mem: &MemCtx) -> u16 { | ||
| if self.valid { | ||
| *mem.read(self.gpa_used_event).unwrap() | ||
| } else { | ||
| 0 | ||
| } |
There was a problem hiding this comment.
I realize this is How We Handle if !self.valid already elsewhere, but it seems to me like if the queue has become invalid we are within our rights to bail out of whatever we're doing on that queue. so like, we should return a Result<u16, TheQueueGotUnmapped>, and we should probably do that for flags too.
if we go processing a queue and send a spurious interrupt that's .. fine, because the guest will know it got the queue unmapped and not doing something too ridiculous, or we go processing a queue and don't send an interrupt based on the bogus-ish state we're working from. so this is OK and I'm really not saying we change it, just wondering if you think that change would be a reasonable later change.
There was a problem hiding this comment.
That sounds reasonable. I haven't paged all the code back in to know for certain, but I also wonder if this is just defensive programming anyways, and if we never should be in this situation to begin with? That is, could the device lifecycle state be encoded in such a way (like type-state) that it's impossible to get here and the read could be unconditional?
In any case, I agree leaving it as its own change makes sense as I imagine it could end up touching quite a bit of code.
|
well, i guess you'd need to merge |
FelixMcFelix
left a comment
There was a problem hiding this comment.
I think my original comments were answered at the time. Thanks for the extra exposition!
This adds F_EVENT_IDX support for all virtqueues, but for this commit we enable it for viona only. This is needed to support F_EVENT_IDX for the viona control queue, which is required so that the illumos viona device may offer it for the data queues. It was found that Tx completion interrupts are greatly reduced with this feature support, presumably due to the Linux driver's better use of
avail.used_eventfor interrupt moderation.Adding this support has shown me a 10x reduction in guest Tx completion interrupts when running iperf benchmarks.
We might want to consider another change that lands prior to this one that actively prevents the negotiation of F_EVENT_IDX. Currently, if the host offers it, propolis blindly passes it through to the guest which will happily enable it: leading to the condition where the host and guest use
avail_event/used_event, but the viona ctrl queue implemented by propolis is still using theflagsmethod, ultimately leading to a guest that hangs during boot because it cannot make progress.We can either do that, or we can make extra sure that Omicron picks up the latest propolis before we land this feature in Helios.