thermal: Add ereports - #2639
Conversation
|
@hawkw another open question is "should we send ereports on power-on"? Right now on sidecar which has 8 fans, we'll send 8x "fan is/is not present" messages, and 8x "fan is/is not nominal" messages. I can add some more logic that suppresses this if we want. It seems consistent to send them, but also I don't know if we've observed any "mad rush" of this kind of state transmission, and what we should do if the outgoing ereport queue fills up. We also could pay attention to whether |
| #[derive(Encode)] | ||
| #[ereport(class = "hw.fan.rpm.err", version = 0)] | ||
| struct FanRpmReadFailed { | ||
| id: u32, | ||
| } |
There was a problem hiding this comment.
part of me thinks we might really want to have a more general ereport in the shared ereports crate for "trying to read a sensor over I2C failed"?
There was a problem hiding this comment.
I would be open to discuss this! How do we still maintain the context: "this i2c read is specifically for a fan and we are sad we don't have its data"?
There was a problem hiding this comment.
So, I was thinking more that we might want to have a conventional field name/payload structure for an I2C read error that would include the raw response code and either a refdes or a controller/bus/mux/addr (I think refdes is more concise) and include that structure in any I2C error ereport. Having that payload struct be included in the "fan sensor read error" ereport is how we would indicate it was for a fan.
I think it's fine to punt on this now and go and factor it out only once we are trying to make ereports like this in multiple places.
This is something I have thought about doing in several places. I think it's not a bad idea, although one deficiency in the way ereports are currently implemented is that the timestamp is always decided by For now, we haven't actually ever dropped ereports due to full buffers, so I haven't been worrying about retries too much yet. |
Do we have a way to reasonably detect when this happens? I can add a little stress and see if we hit it, and back off if not. |
there are ringbuf counters in each task that will tell you precisely how many times it tried and failed to submit an ereport. but, more importantly, the ereport ring buffer code in packrat will create a "loss report" for upstack software that tells it "hey, i have dropped this many ereports, sorry about that". this is part of the same stream as the actual ereports. as far as i know, we have never actually seen such a loss report in a production system.
for what it's worth, such a test is really only going to be interesting if there is a control plane collecting ereports (and therefore draining the buffer); if you run it against a bench system, you will see a bunch of stuff get dropped, but that's kind of anticipated. |
| Fps::TooFast(rpm) => Trace::FanOverspeed(id, rpm), | ||
| Fps::TooSlow(rpm) => Trace::FanUnderspeed(id, rpm), | ||
| let fan_info = || FanInfo { | ||
| name: fan.name, |
There was a problem hiding this comment.
So @hawkw interesting point here:
If I do id.name() here, it ends up inflating the .rodata, likely with the table of all sensor names:
james@fool:~/oxide/hubris git:(james/ereport-thermals) ✗ arm-none-eabi-size -A target/cosmo-b-dev/dist/thermal.elf
target/cosmo-b-dev/dist/thermal.elf :
section size addr
.text 17632 0
.rodata 4640 0
.data 580 0
.bss 2452 0
But with the change to make .name() a const fn, and storing .name in the const-fn constructor of Fan::new(), then we don't pull in the whole array:
james@fool:~/oxide/hubris git:(james/ereport-thermals) ✗ arm-none-eabi-size -A target/cosmo-b-dev/dist/thermal.elf
target/cosmo-b-dev/dist/thermal.elf :
section size addr
.text 17544 0
.rodata 2552 0
.data 628 0
.bss 2452 0
.uninit 0 0
I don't think this is a make or break, a ~2KiB flash difference (on cosmo) isn't really THAT big of a deal, but it does seem lightly footgun-y if you aren't Too Clever about it.
|
@hawkw this should be ready for a fresh look, IMO. |
hawkw
left a comment
There was a problem hiding this comment.
I left some suggestions on the ereport structures. I would really like it if we could figure out a way to get the fan slot numbers as marked on the Sidecar chassis here, but I realize there may not be a great way to do that with the way the sensor config works currently...
| #[derive(Encode)] | ||
| #[ereport(class = "hw.fan.rpm.err", version = 0)] | ||
| struct FanRpmReadFailed { | ||
| id: u32, | ||
| } |
There was a problem hiding this comment.
So, I was thinking more that we might want to have a conventional field name/payload structure for an I2C read error that would include the raw response code and either a refdes or a controller/bus/mux/addr (I think refdes is more concise) and include that structure in any I2C error ereport. Having that payload struct be included in the "fan sensor read error" ereport is how we would indicate it was for a fan.
I think it's fine to punt on this now and go and factor it out only once we are trying to make ereports like this in multiple places.
|
@hawkw one thing I noticed is that there is a slight discrepancy in how we number fans at the chassis level and how the thermal task "thinks" about fans. For example on sidecar:
The chassis thinks in terms of "fan assemblies", each of which are a pair of counter-rotating fans with individual control and monitoring. When reporting in the ereport, would you like the slot to reflect the chassis numbering (e.g. we'll have In 04bc618 I added plumbing for the "slot" field to the ereport, but the numbering currently is almost certainly wrong (I need to make sure that the ordering defined in the BSP initializer matches the schematic/chassis at least for all PCBAs). edit: The fans are also definitely not numbered in the order that I've placed them in currently:
|
|
Also @hawkw should we rename these functions to hubris/task/sensor-api/src/lib.rs Lines 85 to 102 in 1cbf835 |
|
Chatted with @hawkw:
|


Adds ereports for the thermal task, as a follow up to #2630
closes #2603