Skip to content

Commit 7501828

Browse files
committed
packrat: Add helper API for serde ereports (#2225)
In practice, so far, most ereport payloads have been defined as structs implementing `serde::Serialize` and encoded using the `minicbor-serde` adapter crate. This requires a bit of boilerplate code, so it seems worthwhile to provide a method that just does that. This commit adds one in `task-packrat-api`. It's feature-flagged so we can avoid compiling `minicbor`, `minicbor-serde`, and `serde` in tasks that don't submit ereports using this.
1 parent 3f9272f commit 7501828

File tree

7 files changed

+75
-44
lines changed

7 files changed

+75
-44
lines changed

Cargo.lock

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

drv/cosmo-seq-server/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ gnarle = { path = "../../lib/gnarle" }
2020
ringbuf = { path = "../../lib/ringbuf" }
2121
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }
2222
task-jefe-api = { path = "../../task/jefe-api" }
23-
task-packrat-api = { path = "../../task/packrat-api" }
23+
task-packrat-api = { path = "../../task/packrat-api", features = ["serde"] }
2424

2525
cfg-if = { workspace = true }
2626
idol-runtime.workspace = true
2727
num-traits = { workspace = true }
28-
minicbor = { workspace = true }
29-
minicbor-serde = { workspace = true }
3028
pmbus = { workspace = true }
3129
serde = { workspace = true }
3230
zerocopy = { workspace = true }

drv/cosmo-seq-server/src/vcore.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ enum Trace {
7373
StatusMfrSpecific(Rail, Result<u8, ResponseCode>),
7474
I2cError(Rail, PmbusCmd, raa229620a::Error),
7575
EreportSent(Rail, usize),
76-
EreportLost(Rail, usize, packrat::EreportWriteError),
76+
EreportLost(Rail, usize, task_packrat_api::EreportWriteError),
7777
EreportTooBig(Rail),
7878
}
7979

@@ -444,24 +444,13 @@ fn deliver_ereport(
444444
data: &impl serde::Serialize,
445445
) {
446446
let mut ereport_buf = [0u8; 256];
447-
let writer = minicbor::encode::write::Cursor::new(&mut ereport_buf[..]);
448-
let mut s = minicbor_serde::Serializer::new(writer);
449-
match data.serialize(&mut s) {
450-
Ok(_) => {
451-
let len = s.into_encoder().into_writer().position();
452-
match packrat.deliver_ereport(&ereport_buf[..len]) {
453-
Ok(_) => {
454-
ringbuf_entry!(Trace::EreportSent(rail, len));
455-
}
456-
Err(e) => {
457-
ringbuf_entry!(Trace::EreportLost(rail, len, e));
458-
}
459-
}
460-
ringbuf_entry!(Trace::EreportSentOff(rail, len));
447+
match packrat.serialize_ereport(data, &mut ereport_buf[..]) {
448+
Ok(len) => ringbuf_entry!(Trace::EreportSent(rail, len)),
449+
Err(task_packrat_api::EreportSerializeError::Packrat { len, err }) => {
450+
ringbuf_entry!(Trace::EreportLost(rail, len, err))
461451
}
462-
Err(_) => {
463-
// XXX(eliza): ereport didn't fit in buffer...what do
464-
ringbuf_entry!(Trace::EreportTooBig(rail));
452+
Err(task_packrat_api::EreportSerializeError::Serialize(_)) => {
453+
ringbuf_entry!(Trace::EreportTooBig(rail))
465454
}
466455
}
467456
}

drv/gimlet-seq-server/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ counters = { path = "../../lib/counters" }
1818
gnarle = { path = "../../lib/gnarle" }
1919
ringbuf = { path = "../../lib/ringbuf" }
2020
task-jefe-api = { path = "../../task/jefe-api" }
21-
task-packrat-api = { path = "../../task/packrat-api" }
21+
task-packrat-api = { path = "../../task/packrat-api", features = ["serde"] }
2222
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }
2323

2424
cfg-if = { workspace = true }
@@ -30,8 +30,6 @@ zerocopy-derive = { workspace = true }
3030
num-derive = { workspace = true }
3131
static_assertions = { workspace = true }
3232
spd = { workspace = true }
33-
minicbor = { workspace = true }
34-
minicbor-serde = { workspace = true }
3533
serde = { workspace = true }
3634
pmbus = { workspace = true }
3735

drv/gimlet-seq-server/src/vcore.rs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -339,23 +339,13 @@ struct Ereport {
339339
#[inline(never)]
340340
fn deliver_ereport(packrat: &packrat_api::Packrat, data: &impl Serialize) {
341341
let mut ereport_buf = [0u8; 128];
342-
let writer = minicbor::encode::write::Cursor::new(&mut ereport_buf[..]);
343-
let mut s = minicbor_serde::Serializer::new(writer);
344-
match data.serialize(&mut s) {
345-
Ok(_) => {
346-
let len = s.into_encoder().into_writer().position();
347-
match packrat.deliver_ereport(&ereport_buf[..len]) {
348-
Ok(_) => {
349-
ringbuf_entry!(Trace::EreportSent(len));
350-
}
351-
Err(e) => {
352-
ringbuf_entry!(Trace::EreportLost(len, e));
353-
}
354-
}
342+
match packrat.serialize_ereport(data, &mut ereport_buf[..]) {
343+
Ok(len) => ringbuf_entry!(Trace::EreportSent(len)),
344+
Err(task_packrat_api::EreportSerializeError::Packrat { len, err }) => {
345+
ringbuf_entry!(Trace::EreportLost(len, err))
355346
}
356-
Err(_) => {
357-
// XXX(eliza): ereport didn't fit in buffer...what do
358-
ringbuf_entry!(Trace::EreportTooBig);
347+
Err(task_packrat_api::EreportSerializeError::Serialize(_)) => {
348+
ringbuf_entry!(Trace::EreportTooBig)
359349
}
360350
}
361351
}

task/packrat-api/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ name = "task-packrat-api"
33
version = "0.1.0"
44
edition = "2021"
55

6+
[features]
7+
# Enable Serde support for the ereport API.
8+
serde = ["dep:serde", "dep:minicbor", "dep:minicbor-serde"]
9+
610
[dependencies]
711
counters = { path = "../../lib/counters" }
812
derive-idol-err.path = "../../lib/derive-idol-err"
@@ -12,7 +16,10 @@ userlib.path = "../../sys/userlib"
1216

1317
gateway-ereport-messages.workspace = true
1418
idol-runtime.workspace = true
19+
minicbor = { workspace = true, optional = true }
20+
minicbor-serde = { workspace = true, optional = true }
1521
num-traits.workspace = true
22+
serde = { workspace = true, optional = true }
1623
zerocopy.workspace = true
1724
zerocopy-derive.workspace = true
1825

task/packrat-api/src/lib.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,54 @@ pub enum EreportWriteError {
6969
Lost = 1,
7070
}
7171

72+
/// Errors returned by [`Packrat::serialize_ereport`].
73+
#[derive(counters::Count)]
74+
#[cfg(feature = "serde")]
75+
pub enum EreportSerializeError {
76+
/// The IPC to deliver the serialized ereport failed.
77+
Packrat {
78+
len: usize,
79+
#[count(children)]
80+
err: EreportWriteError,
81+
},
82+
/// Serializing the ereport failed.
83+
Serialize(
84+
minicbor_serde::error::EncodeError<minicbor::encode::write::EndOfSlice>,
85+
),
86+
}
87+
88+
#[cfg(feature = "serde")]
89+
impl Packrat {
90+
/// Deliver an ereport for a value that implements [`serde::Serialize`]. The
91+
/// provided `buf` is used to serialize the value before sending it to
92+
/// Packrat.
93+
pub fn serialize_ereport(
94+
&self,
95+
ereport: &impl serde::Serialize,
96+
buf: &mut [u8],
97+
) -> Result<usize, EreportSerializeError> {
98+
let mut s = {
99+
let writer = minicbor::encode::write::Cursor::new(buf);
100+
minicbor_serde::Serializer::new(writer)
101+
};
102+
103+
// Try to serialize the ereport...
104+
ereport
105+
.serialize(&mut s)
106+
.map_err(EreportSerializeError::Serialize)?;
107+
108+
// Okay, get the buffer back out, and figure out how much of it was
109+
// used.
110+
let writer = s.into_encoder().into_writer();
111+
let len = writer.position();
112+
let buf = writer.into_inner();
113+
114+
// Now, try to send that to Packrat.
115+
self.deliver_ereport(&buf[..len])
116+
.map_err(|err| EreportSerializeError::Packrat { len, err })?;
117+
118+
Ok(len)
119+
}
120+
}
121+
72122
include!(concat!(env!("OUT_DIR"), "/client_stub.rs"));

0 commit comments

Comments
 (0)