Skip to content

Commit 21b3da8

Browse files
committed
Be more specific about version errors, raise min required viona API
The recent multiqueue work includes an unconditional ioctl that was introduced in V6 of the viona API. Propolis' expectation should have been raised then, but it was missed in review; instead, trying to create a vNIC on a too-old OS results in propolis panicking about `Inappropriate ioctl for device`. So, raise the minimum viona API as required. propolis-server will exit at start if the OS is too old. The message wasn't super clear though, complaining that: > viona API version mismatch 4 != 6 so this comes with some adjustments to the version error reporting that now produce this error on a too-old host: > 0: checking version of viona > 1: API version 4 is not at or above 6. OS is too old? propolis-standalone allows you to try running something on a too-old host on the expectation you're actively hacking on either the host or Propolis, so it just offers > ERRO viona: API version 4 is not at or above 6. OS is too old? before continuing on (and in this case, panicking about the an inappropriate ioctl).
1 parent 191305e commit 21b3da8

5 files changed

Lines changed: 42 additions & 48 deletions

File tree

bin/propolis-server/src/lib/initializer.rs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -771,32 +771,27 @@ impl MachineInitializer<'_> {
771771
info!(self.log, "Creating vNIC {}", device_name);
772772
let bdf: pci::Bdf = nic.device_spec.pci_path.into();
773773

774-
// Set viona device parameters if possible.
774+
// Set viona device parameters. The parameters here (copy_data and
775+
// header_pad) require `viona::ApiVersion::V3`, below Propolis'
776+
// minimum of V6, so we can always set them.
775777
//
776778
// The values chosen here are tuned to maximize performance when
777779
// Propolis is used with OPTE in a full Oxide rack deployment,
778780
// although they should not negatively impact use outside those
779781
// conditions. These parameters and their effects (save for
780782
// performance delta) are not guest-visible.
781-
let params = if virtio::viona::api_version()
782-
.expect("can query viona version")
783-
>= virtio::viona::ApiVersion::V3
784-
{
785-
Some(virtio::viona::DeviceParams {
786-
// Loan guest packet data, rather than allocating fresh
787-
// buffers and copying it.
788-
copy_data: false,
789-
// Leave room for underlay encapsulation:
790-
// - ethernet: 14
791-
// - IPv6: 40
792-
// - UDP: 8
793-
// - Geneve: 8–16 (due to options)
794-
// - (and then round up to nearest 8)
795-
header_pad: 80,
796-
})
797-
} else {
798-
None
799-
};
783+
let params = Some(virtio::viona::DeviceParams {
784+
// Loan guest packet data, rather than allocating fresh
785+
// buffers and copying it.
786+
copy_data: false,
787+
// Leave room for underlay encapsulation:
788+
// - ethernet: 14
789+
// - IPv6: 40
790+
// - UDP: 8
791+
// - Geneve: 8–16 (due to options)
792+
// - (and then round up to nearest 8)
793+
header_pad: 80,
794+
});
800795

801796
let viona = virtio::PciVirtioViona::new(
802797
&nic.backend_spec.vnic_name,

bin/propolis-standalone/src/main.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,15 +1251,9 @@ fn setup_instance(
12511251
config::VionaDeviceParams::from_opts(&dev.options)
12521252
.expect("viona params are valid");
12531253

1254-
if viona_params.is_some()
1255-
&& hw::virtio::viona::api_version()
1256-
.expect("can query viona version")
1257-
< hw::virtio::viona::ApiVersion::V3
1258-
{
1259-
// lazy cop-out for now
1260-
panic!("can't set viona params on too-old version");
1261-
}
1262-
1254+
// The viona_params here (currently just copy_data and
1255+
// header_pad) require `viona::ApiVersion::V3`, below
1256+
// Propolis' minimum of V6, so we can always set them.
12631257
let viona = hw::virtio::PciVirtioViona::new(
12641258
vnic_name,
12651259
&hdl,
@@ -1452,18 +1446,12 @@ fn api_version_checks(log: &slog::Logger) -> std::io::Result<()> {
14521446
}
14531447
Err(VersionCheckError {
14541448
component,
1449+
err: source @ Error::TooLow { .. },
14551450
path: _,
1456-
err: Error::Mismatch(act, exp),
14571451
}) => {
14581452
// Make noise about version mismatch, but soldier on and let the
14591453
// user decide if they want to quit
1460-
slog::error!(
1461-
log,
1462-
"{} API version mismatch {} != {}",
1463-
component,
1464-
act,
1465-
exp
1466-
);
1454+
slog::error!(log, "{component}: {source}");
14671455
Ok(())
14681456
}
14691457
Ok(_) => Ok(()),

lib/propolis/src/api_version.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ pub enum Error {
77
#[error("IO Error")]
88
Io(#[from] std::io::Error),
99

10-
#[error("API version {0} did not match expectation {1}")]
11-
Mismatch(u32, u32),
10+
// Newer APIs are backwards compatible with older (for now?), so don't
11+
// bother trying to express "we need a version before .." or any of that.
12+
//
13+
// Also assume that the component being versioned is either part of the OS
14+
// or that the OS version is a decent proxy for it. Not necessarily true in
15+
// general, but true for viona and bhyve.
16+
#[error("API version {have} is not at or above {want}. OS is too old?")]
17+
TooLow { have: u32, want: u32 },
1218
}
1319

1420
#[derive(Debug, thiserror::Error)]

lib/propolis/src/hw/virtio/viona.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,6 @@ impl Inner {
226226
}
227227

228228
/// Configuration parmaeters for the underlying viona device
229-
///
230-
/// These parameters assume an [viona_api::ApiVersion::V3] device
231229
#[derive(Copy, Clone)]
232230
pub struct DeviceParams {
233231
/// When transmitting packets, should viona (allocate and) copy the entire
@@ -237,12 +235,18 @@ pub struct DeviceParams {
237235
/// There is a performance cost to copying the full packet, but it avoids
238236
/// certain issues pertaining to looped-back viona packets being delivered
239237
/// to native zones on the machine.
238+
///
239+
/// This parameter requires [viona_api::ApiVersion::V3] or greater. This is
240+
/// before Propolis' minimum viona API version and can always be set.
240241
pub copy_data: bool,
241242

242243
/// Byte count for padding added to the head of transmitted packets. This
243244
/// padding can be used by subsequent operations in the transmission chain,
244245
/// such as encapsulation, which would otherwise need to re-allocate for the
245246
/// larger header.
247+
///
248+
/// This parameter requires [viona_api::ApiVersion::V3] or greater. This is
249+
/// before Propolis' minimum viona API version and can always be set.
246250
pub header_pad: u16,
247251
}
248252
impl DeviceParams {
@@ -1393,11 +1397,12 @@ use bits::*;
13931397
pub(crate) fn check_api_version() -> Result<(), crate::api_version::Error> {
13941398
let vers = viona_api::api_version()?;
13951399

1396-
// viona only requires the V2 bits for now
1397-
let compare = viona_api::ApiVersion::V2;
1400+
// when setting up a vNIC, Propolis will unconditionally do the SET_PAIRS
1401+
// ioctl, which requires V6.
1402+
let want = viona_api::ApiVersion::V6 as u32;
13981403

1399-
if vers < compare {
1400-
Err(crate::api_version::Error::Mismatch(vers, compare as u32))
1404+
if vers < want {
1405+
Err(crate::api_version::Error::TooLow { have: vers, want })
14011406
} else {
14021407
Ok(())
14031408
}

lib/propolis/src/vmm/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ pub(crate) fn check_api_version() -> Result<(), crate::api_version::Error> {
1919
let vers = ctl.api_version()?;
2020

2121
// propolis only requires the bits provided by V8, currently
22-
let compare = bhyve_api::ApiVersion::V8;
22+
let want = bhyve_api::ApiVersion::V8 as u32;
2323

24-
if vers < compare {
25-
return Err(crate::api_version::Error::Mismatch(vers, compare as u32));
24+
if vers < want {
25+
return Err(crate::api_version::Error::TooLow { have: vers, want });
2626
}
2727

2828
Ok(())

0 commit comments

Comments
 (0)