Skip to content

Commit 1da884e

Browse files
committed
Refactoring, newtype for DLS Link IDs
1 parent 360955c commit 1da884e

File tree

3 files changed

+171
-144
lines changed

3 files changed

+171
-144
lines changed

xde/src/dls/mod.rs

Lines changed: 89 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,103 @@
88
99
pub mod sys;
1010

11-
use crate::mac::mac_client_promisc_type_t;
12-
use crate::mac::mac_promisc_add;
13-
use crate::mac::mac_rx_fn;
11+
use crate::mac::mac_client_handle;
12+
use crate::mac::MacClient;
1413
use crate::mac::MacPerimeterHandle;
15-
use crate::mac::MacPromiscHandle;
1614
use crate::mac::MacTxFlags;
1715
use crate::mac::MAC_DROP_ON_NO_DESC;
1816
use alloc::sync::Arc;
19-
use core::ffi::c_void;
17+
use core::ffi::CStr;
18+
use core::fmt::Display;
2019
use core::mem::MaybeUninit;
2120
use core::ptr;
2221
use illumos_sys_hdrs::c_int;
2322
use illumos_sys_hdrs::datalink_id_t;
2423
use illumos_sys_hdrs::uintptr_t;
24+
use illumos_sys_hdrs::ENOENT;
2525
use opte::engine::packet::Packet;
2626
use opte::engine::packet::PacketState;
2727
pub use sys::*;
2828

29+
/// An integer ID used by DLS to refer to a given link.
30+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31+
pub struct LinkId(u32);
32+
33+
impl LinkId {
34+
/// Request the link ID for a device using its name.
35+
pub fn from_name(name: impl AsRef<CStr>) -> Result<Self, LinkError> {
36+
let mut link_id = 0;
37+
38+
unsafe {
39+
match dls_mgmt_get_linkid(name.as_ref().as_ptr(), &mut link_id) {
40+
0 => Ok(LinkId(link_id)),
41+
ENOENT => Err(LinkError::NotFound),
42+
err => Err(LinkError::Other(err)),
43+
}
44+
}
45+
}
46+
}
47+
48+
impl From<LinkId> for datalink_id_t {
49+
fn from(val: LinkId) -> Self {
50+
val.0
51+
}
52+
}
53+
54+
/// Errors encountered while querying DLS for a `LinkId`.
55+
pub enum LinkError {
56+
NotFound,
57+
Other(i32),
58+
}
59+
60+
impl Display for LinkError {
61+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62+
match self {
63+
LinkError::NotFound => write!(f, "link not found"),
64+
LinkError::Other(e) => write!(f, "unknown error ({e})"),
65+
}
66+
}
67+
}
68+
69+
/// A hold on an existing link managed by DLS.
2970
#[derive(Debug)]
3071
pub struct DlsLink {
3172
inner: Option<DlsLinkInner>,
73+
link: LinkId,
3274
}
3375

3476
#[derive(Debug)]
35-
pub struct DlsLinkInner {
77+
struct DlsLinkInner {
3678
dlp: *mut dls_link,
3779
dlh: dls_dl_handle,
38-
link: datalink_id_t,
3980
}
4081

4182
impl DlsLink {
83+
/// Place a hold on an existing link,
4284
pub fn hold(mph: &MacPerimeterHandle) -> Result<Self, c_int> {
4385
let mut dlp = ptr::null_mut();
4486
let mut dlh = ptr::null_mut();
45-
let link = mph.linkid();
87+
let link = mph.link_id();
4688

47-
let res = unsafe { dls_devnet_hold_link(link, &mut dlh, &mut dlp) };
89+
let res =
90+
unsafe { dls_devnet_hold_link(link.into(), &mut dlh, &mut dlp) };
4891
if res == 0 {
49-
Ok(Self { inner: Some(DlsLinkInner { dlp, dlh, link }) })
92+
Ok(Self { inner: Some(DlsLinkInner { dlp, dlh }), link })
5093
} else {
5194
Err(res)
5295
}
5396
}
5497

98+
pub fn link_id(&self) -> LinkId {
99+
self.link
100+
}
101+
55102
// XXX: cleanup REQUIRES that we hold the MAC perimeter handle.
56103
pub fn release(mut self, mph: &MacPerimeterHandle) {
57104
if let Some(inner) = self.inner.take() {
58-
if mph.linkid() != inner.link {
59-
panic!("Tried to free link hold with the wrong MAC perimeter: saw {}, wanted {}",
60-
mph.linkid(), inner.link);
105+
if mph.link_id() != self.link {
106+
panic!("Tried to free link hold with the wrong MAC perimeter: saw {:?}, wanted {:?}",
107+
mph.link_id(),self.link);
61108
}
62109
unsafe {
63110
dls_devnet_rele_link(inner.dlh, inner.dlp);
@@ -73,9 +120,9 @@ impl DlsLink {
73120
return Err(-1);
74121
};
75122

76-
if mph.linkid() != inner.link {
77-
panic!("Tried to open stream with the wrong MAC perimeter: saw {}, wanted {}",
78-
mph.linkid(), inner.link);
123+
if mph.link_id() != self.link {
124+
panic!("Tried to open stream with the wrong MAC perimeter: saw {:?}, wanted {:?}",
125+
mph.link_id(),self.link);
79126
}
80127

81128
let mut stream = MaybeUninit::zeroed();
@@ -86,7 +133,8 @@ impl DlsLink {
86133
_ = self.inner.take();
87134
let dld_str = unsafe { stream.assume_init() };
88135
Ok(DldStream {
89-
inner: Some(DldStreamInner { dld_str, link: mph.linkid() }),
136+
inner: Some(DldStreamInner { dld_str }),
137+
link: mph.link_id(),
90138
}
91139
.into())
92140
} else {
@@ -98,58 +146,30 @@ impl DlsLink {
98146

99147
impl Drop for DlsLink {
100148
fn drop(&mut self) {
101-
if let Some(inner) = self.inner.take() {
149+
if self.inner.take().is_some() {
102150
opte::engine::err!(
103-
"dropped hold on link {} without releasing!!",
104-
inner.link
151+
"dropped hold on link {:?} without releasing!!",
152+
self.link
105153
);
106154
}
107155
}
108156
}
109157

158+
/// A DLS message stream derived from a
110159
#[derive(Debug)]
111160
pub struct DldStream {
112161
inner: Option<DldStreamInner>,
162+
link: LinkId,
113163
}
114164

115165
#[derive(Debug)]
116-
pub struct DldStreamInner {
166+
struct DldStreamInner {
117167
dld_str: dld_str_s,
118-
link: datalink_id_t,
119168
}
120169

121170
impl DldStream {
122-
/// Register promiscuous callback to receive packets on the underlying MAC.
123-
pub fn add_promisc(
124-
self: &Arc<Self>,
125-
ptype: mac_client_promisc_type_t,
126-
promisc_fn: mac_rx_fn,
127-
flags: u16,
128-
) -> Result<MacPromiscHandle<Self>, c_int> {
129-
let Some(inner) = self.inner.as_ref() else {
130-
return Err(-1);
131-
};
132-
133-
let mut mph = ptr::null_mut();
134-
135-
// `MacPromiscHandle` keeps a reference to this `MacClientHandle`
136-
// until it is removed and so we can safely access it from the
137-
// callback via the `arg` pointer.
138-
let _parent = self.clone();
139-
let parent = Arc::into_raw(_parent) as *mut _;
140-
let arg = parent as *mut c_void;
141-
let mch = inner.dld_str.ds_mch;
142-
let ret = unsafe {
143-
// NOTE: arg is reinterpreted as `mac_resource_handle` -> `mac_ring`
144-
// in `mac_rx_common`. Is what we've been doing here and before even safe?
145-
mac_promisc_add(mch, ptype, promisc_fn, arg, &mut mph, flags)
146-
};
147-
148-
if ret == 0 {
149-
Ok(MacPromiscHandle { mph, parent })
150-
} else {
151-
Err(ret)
152-
}
171+
pub fn link_id(&self) -> LinkId {
172+
self.link
153173
}
154174

155175
pub fn tx_drop_on_no_desc(
@@ -180,9 +200,9 @@ impl DldStream {
180200
// XXX: cleanup REQUIRES that we hold the MAC perimeter handle.
181201
pub fn release(mut self, mph: &MacPerimeterHandle) {
182202
if let Some(mut inner) = self.inner.take() {
183-
if mph.linkid() != inner.link {
184-
opte::engine::err!("Tried to free link hold with the wrong MAC perimeter: saw {}, wanted {}",
185-
mph.linkid(), inner.link);
203+
if mph.link_id() != self.link {
204+
opte::engine::err!("Tried to free link hold with the wrong MAC perimeter: saw {:?}, wanted {:?}",
205+
mph.link_id(), self.link);
186206
}
187207
unsafe {
188208
dls_close(&mut inner.dld_str);
@@ -191,12 +211,22 @@ impl DldStream {
191211
}
192212
}
193213

214+
impl MacClient for DldStream {
215+
fn mac_client_handle(&self) -> Result<*mut mac_client_handle, c_int> {
216+
let Some(inner) = self.inner.as_ref() else {
217+
return Err(-1);
218+
};
219+
220+
Ok(inner.dld_str.ds_mch)
221+
}
222+
}
223+
194224
impl Drop for DldStream {
195225
fn drop(&mut self) {
196-
if let Some(inner) = self.inner.take() {
226+
if self.inner.take().is_some() {
197227
opte::engine::err!(
198-
"dropped stream on link {} without releasing!!",
199-
inner.link
228+
"dropped stream on link {:?} without releasing!!",
229+
self.link,
200230
);
201231
}
202232
}

xde/src/mac/mod.rs

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! the moment out of laziness.
1111
pub mod sys;
1212

13+
use crate::dls::LinkId;
1314
use alloc::ffi::CString;
1415
use alloc::string::String;
1516
use alloc::string::ToString;
@@ -198,37 +199,6 @@ impl MacClientHandle {
198199
}
199200
}
200201

201-
/// Register promiscuous callback to receive packets on the underlying MAC.
202-
pub fn add_promisc(
203-
self: &Arc<Self>,
204-
ptype: mac_client_promisc_type_t,
205-
promisc_fn: mac_rx_fn,
206-
flags: u16,
207-
) -> Result<MacPromiscHandle<Self>, c_int> {
208-
let mut mph = ptr::null_mut();
209-
210-
// `MacPromiscHandle` keeps a reference to this `MacClientHandle`
211-
// until it is removed and so we can safely access it from the
212-
// callback via the `arg` pointer.
213-
let mch = Arc::into_raw(self.clone());
214-
let ret = unsafe {
215-
mac_promisc_add(
216-
self.mch,
217-
ptype,
218-
promisc_fn,
219-
mch as *mut c_void,
220-
&mut mph,
221-
flags,
222-
)
223-
};
224-
225-
if ret == 0 {
226-
Ok(MacPromiscHandle { mph, parent: mch })
227-
} else {
228-
Err(ret)
229-
}
230-
}
231-
232202
/// Send the [`Packet`] on this client.
233203
///
234204
/// If the packet cannot be sent, return it. If you want to drop
@@ -300,15 +270,52 @@ impl Drop for MacClientHandle {
300270
}
301271
}
302272

273+
pub trait MacClient {
274+
fn mac_client_handle(&self) -> Result<*mut mac_client_handle, c_int>;
275+
}
276+
277+
impl MacClient for MacClientHandle {
278+
fn mac_client_handle(&self) -> Result<*mut mac_client_handle, c_int> {
279+
Ok(self.mch)
280+
}
281+
}
282+
303283
/// Safe wrapper around a `mac_promisc_handle_t`.
304284
#[derive(Debug)]
305285
pub struct MacPromiscHandle<P> {
306286
/// The underlying `mac_promisc_handle_t`.
307-
pub(crate) mph: *mut mac_promisc_handle,
287+
mph: *mut mac_promisc_handle,
288+
289+
/// The parent used to create this promiscuous callback.
290+
parent: *const P,
291+
}
292+
293+
impl<P: MacClient> MacPromiscHandle<P> {
294+
/// Register a promiscuous callback to receive packets on the underlying MAC.
295+
pub fn new(
296+
parent: Arc<P>,
297+
ptype: mac_client_promisc_type_t,
298+
promisc_fn: mac_rx_fn,
299+
flags: u16,
300+
) -> Result<MacPromiscHandle<P>, c_int> {
301+
let mut mph = ptr::null_mut();
302+
let mch = parent.mac_client_handle()?;
303+
let parent = Arc::into_raw(parent);
304+
let arg = parent as *mut c_void;
305+
306+
// SAFETY: `MacPromiscHandle` keeps a reference to this `P`
307+
// until it is removed and so we can safely access it from the
308+
// callback via the `arg` pointer.
309+
let ret = unsafe {
310+
mac_promisc_add(mch, ptype, promisc_fn, arg, &mut mph, flags)
311+
};
308312

309-
/// The `MacClientHandle` used to create this promiscuous callback.
310-
/// MUST BE A RAW ARC.
311-
pub(crate) parent: *const P,
313+
if ret == 0 {
314+
Ok(Self { mph, parent })
315+
} else {
316+
Err(ret)
317+
}
318+
}
312319
}
313320

314321
impl<P> Drop for MacPromiscHandle<P> {
@@ -342,26 +349,26 @@ impl Drop for MacUnicastHandle {
342349
}
343350
}
344351

345-
// XXX: cleanup
346-
347352
/// Safe wrapper around a `mac_perim_handle_t`.
348353
pub struct MacPerimeterHandle {
349354
mph: mac_perim_handle,
350-
link: datalink_id_t,
355+
link: LinkId,
351356
}
352357

353358
impl MacPerimeterHandle {
354-
pub fn from_linkid(link: datalink_id_t) -> Result<Self, c_int> {
359+
/// Attempt to acquire the MAC perimeter for a given link.
360+
pub fn from_linkid(link: LinkId) -> Result<Self, c_int> {
355361
let mut mph = 0;
356-
let res = unsafe { mac_perim_enter_by_linkid(link, &mut mph) };
362+
let res = unsafe { mac_perim_enter_by_linkid(link.into(), &mut mph) };
357363
if res == 0 {
358364
Ok(Self { mph, link })
359365
} else {
360366
Err(res)
361367
}
362368
}
363369

364-
pub fn linkid(&self) -> datalink_id_t {
370+
/// Returns the ID of the link whose MAC perimeter is held.
371+
pub fn link_id(&self) -> LinkId {
365372
self.link
366373
}
367374
}

0 commit comments

Comments
 (0)