forked from openbmc/dbus-sensors
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add mctpreactor for dynamic configuration of MCTP networks
While mctpd[1] may see heavy use in projects such as OpenBMC, it implements generic functionality necessary to operate MCTP as a protocol. It therefore should be easy to use in other contexts, and so it feels unwise to embed OpenBMC-specific details in its implementation. Conversely, entity-manager's scope is to expose inventory and board configuration. It externalises all other responsibilities for the sake of stability and maintenance. While entity-manager is central to OpenBMC's implementation and has little use in other contexts, embedding details of how to configure mctpd in entity-manager exceeds its scope. Thus we reach the design point of mctpreactor, an intermediary process that encapsulates OpenBMC-specific and mctpd-specific behaviors to constrain their dispersion in either direction. The design-point was reached via discussion at [2]. mctpreactor tracks instances of transport-specific MCTP device configurations appearing as a result of inventory changes, and uses them to assign endpoint IDs via mctpd. The lifecycle of an MCTP device can be quite dynamic - mctpd provides behaviors to recover[3] or remove endpoints from the network. Their presence cannot be assumed. mctpreactor handles these events: If a device is removed at the MCTP layer (as it may be unresponsive), mctpreactor will periodically attempt to re-establish it as an endpoint so long as the associated configuration on the entity-manager inventory object remains exposed. [1]: https://github.com/CodeConstruct/mctp/ [2]: CodeConstruct/mctp#17 [3]: https://github.com/CodeConstruct/mctp/blob/7ec2f8daa3a8948066390aee621d6afa03f6ecd9/docs/endpoint-recovery.md Change-Id: I5e362cf6e5ce80ce282bab48d912a1038003e236 Signed-off-by: Andrew Jeffery <[email protected]>
- Loading branch information
Showing
13 changed files
with
1,494 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[Unit] | ||
Description=MCTP device configuration | ||
StopWhenUnneeded=false | ||
Requires=xyz.openbmc_project.EntityManager.service | ||
After=xyz.openbmc_project.EntityManager.service | ||
|
||
[Service] | ||
Restart=always | ||
RestartSec=5 | ||
ExecStart=/usr/bin/mctpreactor | ||
|
||
[Install] | ||
WantedBy=multi-user.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
#pragma once | ||
|
||
#include "MCTPEndpoint.hpp" | ||
|
||
class MCTPDeviceRepository | ||
{ | ||
private: | ||
// FIXME: Ugh, hack. Figure out a better data structure? | ||
std::map<std::string, std::shared_ptr<MCTPDevice>> devices; | ||
|
||
auto lookup(const std::shared_ptr<MCTPDevice>& device) | ||
{ | ||
auto pred = [&device](const auto& it) { return it.second == device; }; | ||
return std::ranges::find_if(devices, pred); | ||
} | ||
|
||
public: | ||
MCTPDeviceRepository() = default; | ||
MCTPDeviceRepository(const MCTPDeviceRepository&) = delete; | ||
MCTPDeviceRepository(MCTPDeviceRepository&&) = delete; | ||
~MCTPDeviceRepository() = default; | ||
|
||
MCTPDeviceRepository& operator=(const MCTPDeviceRepository&) = delete; | ||
MCTPDeviceRepository& operator=(MCTPDeviceRepository&&) = delete; | ||
|
||
void add(const std::string& inventory, | ||
const std::shared_ptr<MCTPDevice>& device) | ||
{ | ||
auto [_, fresh] = devices.emplace(inventory, device); | ||
if (!fresh) | ||
{ | ||
throw std::logic_error( | ||
std::format("Tried to add entry for existing device: {}", | ||
device->describe())); | ||
} | ||
} | ||
|
||
void remove(const std::shared_ptr<MCTPDevice>& device) | ||
{ | ||
auto entry = lookup(device); | ||
if (entry == devices.end()) | ||
{ | ||
throw std::logic_error( | ||
std::format("Trying to remove unknown device: {}", | ||
entry->second->describe())); | ||
} | ||
devices.erase(entry); | ||
} | ||
|
||
void remove(const std::string& inventory) | ||
{ | ||
auto entry = devices.find(inventory); | ||
if (entry == devices.end()) | ||
{ | ||
throw std::logic_error(std::format( | ||
"Trying to remove unknown inventory: {}", inventory)); | ||
} | ||
devices.erase(entry); | ||
} | ||
|
||
bool contains(const std::string& inventory) | ||
{ | ||
return devices.contains(inventory); | ||
} | ||
|
||
bool contains(const std::shared_ptr<MCTPDevice>& device) | ||
{ | ||
return lookup(device) != devices.end(); | ||
} | ||
|
||
const std::string& inventoryFor(const std::shared_ptr<MCTPDevice>& device) | ||
{ | ||
auto entry = lookup(device); | ||
if (entry == devices.end()) | ||
{ | ||
throw std::logic_error( | ||
std::format("Cannot retrieve inventory for unknown device: {}", | ||
device->describe())); | ||
} | ||
return entry->first; | ||
} | ||
|
||
const std::shared_ptr<MCTPDevice>& deviceFor(const std::string& inventory) | ||
{ | ||
auto entry = devices.find(inventory); | ||
if (entry == devices.end()) | ||
{ | ||
throw std::logic_error(std::format( | ||
"Cannot retrieve device for unknown inventory: {}", inventory)); | ||
} | ||
return entry->second; | ||
} | ||
}; |
Oops, something went wrong.