Skip to content

Commit 4978310

Browse files
committed
mctp-estack: Return ControlEvent from handle_async
Set Endpoint ID now emits an event. In future this can also be implemented for pool-allocation related events. ERROR_INVALID_DATA is now returned for a Reset request (which is not implemented). Signed-off-by: Matt Johnston <[email protected]>
1 parent c9e5f82 commit 4978310

File tree

1 file changed

+82
-40
lines changed

1 file changed

+82
-40
lines changed

mctp-estack/src/control.rs

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,11 @@ pub fn respond_get_eid<'a>(
274274
/// A Set Endpoint ID request.
275275
#[allow(missing_docs)]
276276
#[derive(Debug)]
277-
pub struct SetEndpointId {
278-
pub eid: Eid,
279-
pub force: bool,
280-
pub reset: bool,
277+
pub enum SetEndpointId {
278+
Set(Eid),
279+
Force(Eid),
280+
Reset,
281+
SetDiscovered,
281282
}
282283

283284
/// Parse a Set Endpoint ID request.
@@ -289,30 +290,26 @@ pub fn parse_set_eid(req: &MctpControlMsg) -> ControlResult<SetEndpointId> {
289290
return Err(CompletionCode::ERROR_INVALID_LENGTH);
290291
}
291292

292-
let eid = Eid::new_normal(req.body[1]).map_err(|_| {
293-
warn!("Invalid Set EID {}", req.body[1]);
294-
CompletionCode::ERROR_INVALID_DATA
295-
})?;
296-
297-
let mut ret = SetEndpointId {
298-
eid,
299-
force: false,
300-
reset: false,
301-
};
302-
303-
match req.body[0] & 0x03 {
304-
// Set
305-
0b00 => (),
306-
// Force
307-
0b01 => ret.force = true,
293+
let op = req.body[0] & 0x03;
294+
Ok(match op {
295+
// Set or Force
296+
0b00 | 0b01 => {
297+
let eid = Eid::new_normal(req.body[1]).map_err(|_| {
298+
warn!("Invalid Set EID {}", req.body[1]);
299+
CompletionCode::ERROR_INVALID_DATA
300+
})?;
301+
if op == 0b00 {
302+
SetEndpointId::Set(eid)
303+
} else {
304+
SetEndpointId::Force(eid)
305+
}
306+
}
308307
// Reset
309-
0b10 => ret.reset = true,
308+
0b10 => SetEndpointId::Reset,
310309
// Set Discovered
311-
0b11 => return Err(CompletionCode::ERROR_INVALID_DATA),
310+
0b11 => SetEndpointId::SetDiscovered,
312311
_ => unreachable!(),
313-
}
314-
315-
Ok(ret)
312+
})
316313
}
317314

318315
/// Create a Set Endpoint ID response.
@@ -326,7 +323,13 @@ pub fn respond_set_eid<'a>(
326323
return Err(CompletionCode::ERROR);
327324
}
328325
let status = if accepted { 0b00000000 } else { 0b00010000 };
329-
let body = [CompletionCode::SUCCESS.into(), status, current_eid.0, 0x00];
326+
let pool_size = 0;
327+
let body = [
328+
CompletionCode::SUCCESS.into(),
329+
status,
330+
current_eid.0,
331+
pool_size,
332+
];
330333
let rsp_buf = &mut rsp_buf[0..body.len()];
331334
rsp_buf.clone_from_slice(&body);
332335
req.new_resp(rsp_buf)
@@ -448,22 +451,26 @@ impl<'a> MctpControl<'a> {
448451
&mut self,
449452
msg: &[u8],
450453
mut resp_chan: impl AsyncRespChannel,
451-
) -> mctp::Result<()> {
454+
) -> mctp::Result<Option<ControlEvent>> {
452455
let req = MctpControlMsg::from_buf(msg).map_err(|e| {
453456
// Can't send a response since request couldn't be parsed
454457
debug!("Bad control input {e:?}");
455458
mctp::Error::InvalidInput
456459
})?;
457460

458-
let mut resp = match self.handle_req(&req).await {
459-
Err(e) => {
460-
debug!("Control error response {:?}", e);
461-
respond_error(&req, e, &mut self.rsp_buf)
462-
}
463-
Ok(r) => Ok(r),
464-
}?;
461+
let (mut resp, ev) =
462+
match self.handle_req(&req, resp_chan.remote_eid()).await {
463+
Err(e) => {
464+
debug!("Control error response {:?}", e);
465+
respond_error(&req, e, &mut self.rsp_buf).map(|r| (r, None))
466+
}
467+
Ok(r) => Ok(r),
468+
}?;
465469

466-
resp_chan.send_vectored(MsgIC(false), &resp.slices()).await
470+
resp_chan
471+
.send_vectored(MsgIC(false), &resp.slices())
472+
.await?;
473+
Ok(ev)
467474
}
468475

469476
/// Set MCTP message types to be reported by the handler.
@@ -485,9 +492,11 @@ impl<'a> MctpControl<'a> {
485492
async fn handle_req(
486493
&mut self,
487494
req: &'_ MctpControlMsg<'_>,
488-
) -> ControlResult<MctpControlMsg<'_>> {
495+
source_eid: Eid,
496+
) -> ControlResult<(MctpControlMsg<'_>, Option<ControlEvent>)> {
489497
let cc = req.command_code();
490498

499+
let mut event = None;
491500
#[cfg(feature = "log")]
492501
debug!("Control request {:?}", cc);
493502
match cc {
@@ -496,11 +505,30 @@ impl<'a> MctpControl<'a> {
496505
respond_get_eid(req, eid, 0, &mut self.rsp_buf)
497506
}
498507
CommandCode::SetEndpointID => {
499-
let set = parse_set_eid(req)?;
500-
let res = self.router.set_eid(set.eid).await;
501-
let eid = self.router.get_eid().await;
508+
let (SetEndpointId::Set(eid) | SetEndpointId::Force(eid)) =
509+
parse_set_eid(req)?
510+
else {
511+
// Don't support Reset or SetDiscovered
512+
return Err(CompletionCode::ERROR_INVALID_DATA);
513+
};
514+
let old = self.router.get_eid().await;
515+
let res = self.router.set_eid(eid).await;
516+
let present_eid = self.router.get_eid().await;
517+
518+
if res.is_ok() && old != present_eid {
519+
event = Some(ControlEvent::SetEndpointId {
520+
old,
521+
new: present_eid,
522+
bus_owner: source_eid,
523+
});
524+
}
502525

503-
respond_set_eid(req, res.is_ok(), eid, &mut self.rsp_buf)
526+
respond_set_eid(
527+
req,
528+
res.is_ok(),
529+
present_eid,
530+
&mut self.rsp_buf,
531+
)
504532
}
505533
CommandCode::GetEndpointUUID => {
506534
if let Some(uuid) = self.uuid {
@@ -516,9 +544,23 @@ impl<'a> MctpControl<'a> {
516544
),
517545
_ => Err(CompletionCode::ERROR_UNSUPPORTED_CMD),
518546
}
547+
.map(|r| (r, event))
519548
}
520549
}
521550

551+
/// An MCTP control handler event
552+
pub enum ControlEvent {
553+
/// Set Endpoint ID changed EID
554+
SetEndpointId {
555+
/// Previous EID
556+
old: Eid,
557+
/// New EID
558+
new: Eid,
559+
/// Bus Owner that set the EID
560+
bus_owner: Eid,
561+
},
562+
}
563+
522564
#[cfg(test)]
523565
mod tests {
524566
use super::*;

0 commit comments

Comments
 (0)