Skip to content

Commit

Permalink
Port Mac-friendly KRwLock (#381), fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixMcFelix committed Sep 22, 2023
1 parent 9d7bbf3 commit 5ff40c3
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 21 deletions.
11 changes: 0 additions & 11 deletions crates/illumos-sys-hdrs/src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,6 @@ pub struct krwlock_t {
pub _opaque: u64,
}

/// `krwlock_t` type passed to `rw_init(9F)`.
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct krw_type_t(pub c_int);
impl krw_type_t {
/// Lock for use by (DDI) drivers.
pub const RW_DRIVER: Self = Self(2);
/// Kernel default lock.
pub const RW_DEFAULT: Self = Self(4);
}

/// Lock acquisition type passed to `rw_[try]enter(9F)`.
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq)]
Expand Down
13 changes: 13 additions & 0 deletions crates/illumos-sys-hdrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,19 @@ pub struct kmutex_t {
pub _opaque: u64,
}

// ======================================================================
// uts/common/sys/rwlock.h
// ======================================================================

/// `krwlock_t` type passed to `rw_init(9F)`.
#[repr(C)]
pub enum krw_type_t {
/// Lock for use by (DDI) drivers.
RW_DRIVER = 2,
/// Kernel default lock.
RW_DEFAULT = 4,
}

// ======================================================================
// uts/common/sys/stream.h
// ======================================================================
Expand Down
83 changes: 79 additions & 4 deletions lib/opte/src/ddi/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cfg_if! {
use core::cell::UnsafeCell;
use core::ptr;
use illumos_sys_hdrs::{
kmutex_t, krw_t, krw_type_t, krwlock_t, mutex_enter, mutex_exit,
kmutex_t, krw_t, krwlock_t, mutex_enter, mutex_exit,
mutex_init, rw_enter, rw_exit, rw_init,
};
} else {
Expand All @@ -25,6 +25,7 @@ cfg_if! {
}

use illumos_sys_hdrs::kmutex_type_t;
use illumos_sys_hdrs::krw_type_t;

/// Exposes the illumos mutex(9F) API in a safe manner. We name it
/// `KMutex` (Kernel Mutex) on purpose. The API for a kernel mutex
Expand Down Expand Up @@ -206,10 +207,17 @@ pub struct KRwLock<T> {
data: UnsafeCell<T>,
}

#[cfg(all(not(feature = "std"), not(test)))]
impl<T> KRwLock<T> {
pub fn into_driver(val: T) -> Self {
let mut out = Self::new(val);
out.init(KRwLockType::Driver);
out
}
}

pub enum KRwLockType {
Driver = krw_type_t::RW_DRIVER.0 as isize,
Default = krw_type_t::RW_DEFAULT.0 as isize,
Driver = krw_type_t::RW_DRIVER as isize,
Default = krw_type_t::RW_DEFAULT as isize,
}

#[cfg(all(not(feature = "std"), not(test)))]
Expand Down Expand Up @@ -315,3 +323,70 @@ impl<T> Drop for KRwLockWriteGuard<'_, T> {
unsafe { rw_exit(self.lock.rwl.get()) };
}
}

// In a std environment we just wrap `RwLock`.
#[cfg(any(feature = "std", test))]
pub struct KRwLock<T> {
inner: std::sync::RwLock<T>,
}

#[cfg(any(feature = "std", test))]
pub struct KRwLockReadGuard<'a, T: 'a> {
guard: std::sync::RwLockReadGuard<'a, T>,
}

#[cfg(any(feature = "std", test))]
pub struct KRwLockWriteGuard<'a, T: 'a> {
guard: std::sync::RwLockWriteGuard<'a, T>,
}

#[cfg(any(feature = "std", test))]
impl<T> Deref for KRwLockReadGuard<'_, T> {
type Target = T;

fn deref(&self) -> &T {
self.guard.deref()
}
}

#[cfg(any(feature = "std", test))]
impl<T> Deref for KRwLockWriteGuard<'_, T> {
type Target = T;

fn deref(&self) -> &T {
self.guard.deref()
}
}

#[cfg(any(feature = "std", test))]
impl<T> DerefMut for KRwLockWriteGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
self.guard.deref_mut()
}
}

#[cfg(any(feature = "std", test))]
impl<T> KRwLock<T> {
pub fn into_inner(self) -> T
where
T: Sized,
{
self.inner.into_inner().unwrap()
}

pub fn new(val: T) -> Self {
KRwLock { inner: std::sync::RwLock::new(val) }
}

pub fn init(&mut self, _typ: KRwLockType) {}

pub fn read(&self) -> KRwLockReadGuard<T> {
let guard = self.inner.read().unwrap();
KRwLockReadGuard { guard }
}

pub fn write(&self) -> KRwLockWriteGuard<T> {
let guard = self.inner.write().unwrap();
KRwLockWriteGuard { guard }
}
}
1 change: 0 additions & 1 deletion lib/oxide-vpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,6 @@ mod tests {
},
},
vni: Vni::new(100u32).unwrap(),
dhcp: Default::default(),
}
}

Expand Down
7 changes: 4 additions & 3 deletions lib/oxide-vpc/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod port_state;
// Let's make our lives easier and pub use a bunch of stuff.
pub use opte::api::Direction::*;
pub use opte::api::MacAddr;
pub use opte::ddi::sync::KRwLock;
pub use opte::engine::checksum::HeaderChecksum;
pub use opte::engine::ether::EtherHdr;
pub use opte::engine::ether::EtherMeta;
Expand Down Expand Up @@ -154,7 +155,6 @@ pub fn g1_cfg2(ip_cfg: IpCfg) -> VpcCfg {
]),
vni: Vni::new(99u32).unwrap(),
},
dhcp: base_dhcp_config(),
}
}

Expand Down Expand Up @@ -198,7 +198,6 @@ pub fn g2_cfg() -> VpcCfg {
]),
vni: Vni::new(99u32).unwrap(),
},
dhcp: base_dhcp_config(),
}
}

Expand All @@ -216,8 +215,10 @@ fn oxide_net_builder(
let snat_limit = NonZeroU32::new(8096).unwrap();
let one_limit = NonZeroU32::new(1).unwrap();

let dhcp = Arc::new(KRwLock::into_driver(base_dhcp_config()));

firewall::setup(&mut pb, fw_limit).expect("failed to add firewall layer");
gateway::setup(&pb, cfg, vpc_map, fw_limit)
gateway::setup(&pb, cfg, vpc_map, fw_limit, &dhcp)
.expect("failed to setup gateway layer");
router::setup(&pb, cfg, one_limit).expect("failed to add router layer");
nat::setup(&mut pb, cfg, snat_limit).expect("failed to add nat layer");
Expand Down
5 changes: 3 additions & 2 deletions lib/oxide-vpc/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ fn lab_cfg() -> VpcCfg {
]),
vni: Vni::new(99u32).unwrap(),
},
dhcp: base_dhcp_config(),
}
}

Expand Down Expand Up @@ -2270,14 +2269,16 @@ fn test_reply_to_dhcpv6_solicit_or_request() {
panic!("Expected an IANA option, found {:?}", iana);
}

let used_dhcp = base_dhcp_config();

let domain_list = reply
.find_option(dhcpv6::options::Code::DomainList)
.expect("Expected a Domain Search List option");
let dhcpv6::options::Option::DomainList(bytes) = domain_list else {
panic!("Expected an Option::DomainList");
};
let mut expected_bytes = Vec::new();
for name in g1_cfg.dhcp.domain_search_list.iter() {
for name in used_dhcp.domain_search_list.iter() {
expected_bytes.extend_from_slice(name.encode());
}
assert_eq!(
Expand Down

0 comments on commit 5ff40c3

Please sign in to comment.