blob: d2f7f338d9fae4b658924c53e33cc4bdebf49491 [file] [log] [blame]
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +00001#include "topology.hpp"
2
Alexander Hansen315929a2025-08-19 17:34:10 +02003#include "phosphor-logging/lg2.hpp"
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +00004
5void Topology::addBoard(const std::string& path, const std::string& boardType,
Matt Spinler6eb60972023-08-14 16:36:20 -05006 const std::string& boardName,
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +00007 const nlohmann::json& exposesItem)
8{
9 auto findType = exposesItem.find("Type");
10 if (findType == exposesItem.end())
11 {
12 return;
13 }
Matt Spinler6eb60972023-08-14 16:36:20 -050014
15 boardNames.try_emplace(boardName, path);
16
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000017 PortType exposesType = findType->get<std::string>();
18
19 if (exposesType == "DownstreamPort")
20 {
Alexander Hansenec938ad2025-08-19 16:48:44 +020021 addDownstreamPort(path, exposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000022 }
23 else if (exposesType.ends_with("Port"))
24 {
Alexander Hansen7cfc0432025-08-20 14:43:04 +020025 upstreamPorts[exposesType].insert(path);
Alexander Hansenec938ad2025-08-19 16:48:44 +020026 }
27 else
28 {
29 return;
30 }
31 boardTypes[path] = boardType;
32}
33
34void Topology::addDownstreamPort(const Path& path,
35 const nlohmann::json& exposesItem)
36{
37 auto findConnectsTo = exposesItem.find("ConnectsToType");
38 if (findConnectsTo == exposesItem.end())
39 {
Alexander Hansen315929a2025-08-19 17:34:10 +020040 lg2::error("Board at path {PATH} is missing ConnectsToType", "PATH",
41 path);
Alexander Hansenec938ad2025-08-19 16:48:44 +020042 return;
43 }
44 PortType connectsTo = findConnectsTo->get<std::string>();
45
Alexander Hansen7cfc0432025-08-20 14:43:04 +020046 downstreamPorts[connectsTo].insert(path);
Alexander Hansenec938ad2025-08-19 16:48:44 +020047 auto findPoweredBy = exposesItem.find("PowerPort");
48 if (findPoweredBy != exposesItem.end())
49 {
50 powerPaths.insert(path);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000051 }
52}
53
Alexander Hansen0519f572025-08-19 18:11:04 +020054std::unordered_map<std::string, std::set<Association>> Topology::getAssocs(
Alexander Hansen32e74182025-08-20 16:16:00 +020055 BoardPathsView boardPaths)
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000056{
Alexander Hansen0519f572025-08-19 18:11:04 +020057 std::unordered_map<std::string, std::set<Association>> result;
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000058
59 // look at each upstream port type
60 for (const auto& upstreamPortPair : upstreamPorts)
61 {
62 auto downstreamMatch = downstreamPorts.find(upstreamPortPair.first);
63
64 if (downstreamMatch == downstreamPorts.end())
65 {
66 // no match
67 continue;
68 }
69
Alexander Hansend7be0ee2025-08-20 14:16:15 +020070 fillAssocsForPortId(result, boardPaths, upstreamPortPair.second,
71 downstreamMatch->second);
72 }
73 return result;
74}
75
76void Topology::fillAssocsForPortId(
77 std::unordered_map<std::string, std::set<Association>>& result,
78 BoardPathsView boardPaths, const std::set<Path>& upstreamPaths,
79 const std::set<Path>& downstreamPaths)
80{
81 for (const Path& upstream : upstreamPaths)
82 {
Alexander Hansen97a1c932025-08-20 16:28:52 +020083 for (const Path& downstream : downstreamPaths)
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000084 {
Alexander Hansen97a1c932025-08-20 16:28:52 +020085 fillAssocForPortId(result, boardPaths, upstream, downstream);
86 }
87 }
88}
89
90void Topology::fillAssocForPortId(
91 std::unordered_map<std::string, std::set<Association>>& result,
92 BoardPathsView boardPaths, const Path& upstream, const Path& downstream)
93{
Alexander Hansen5036d942025-08-20 16:38:59 +020094 if (boardTypes[upstream] != "Chassis" && boardTypes[upstream] != "Board")
Alexander Hansen97a1c932025-08-20 16:28:52 +020095 {
Alexander Hansen5036d942025-08-20 16:38:59 +020096 return;
97 }
98 // The downstream path must be one we care about.
99 if (!std::ranges::contains(boardPaths, downstream))
100 {
101 return;
102 }
103
104 result[downstream].insert({"contained_by", "containing", upstream});
105
106 if (powerPaths.contains(downstream))
107 {
108 result[downstream].insert({"powering", "powered_by", upstream});
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000109 }
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000110}
Matt Spinler6eb60972023-08-14 16:36:20 -0500111
112void Topology::remove(const std::string& boardName)
113{
114 // Remove the board from boardNames, and then using the path
115 // found in boardNames remove it from upstreamPorts and
116 // downstreamPorts.
117 auto boardFind = boardNames.find(boardName);
118 if (boardFind == boardNames.end())
119 {
120 return;
121 }
122
123 std::string boardPath = boardFind->second;
124
125 boardNames.erase(boardFind);
126
Alexander Hansenf3bb8d92025-08-19 16:21:43 +0200127 for (auto& upstreamPort : upstreamPorts)
Matt Spinler6eb60972023-08-14 16:36:20 -0500128 {
Alexander Hansen7cfc0432025-08-20 14:43:04 +0200129 upstreamPort.second.erase(boardPath);
Matt Spinler6eb60972023-08-14 16:36:20 -0500130 }
131
Alexander Hansenf3bb8d92025-08-19 16:21:43 +0200132 for (auto& downstreamPort : downstreamPorts)
Matt Spinler6eb60972023-08-14 16:36:20 -0500133 {
Alexander Hansen7cfc0432025-08-20 14:43:04 +0200134 downstreamPort.second.erase(boardPath);
Matt Spinler6eb60972023-08-14 16:36:20 -0500135 }
136}