xref: /openbmc/entity-manager/src/topology.cpp (revision bfda2c43)
1 #include "topology.hpp"
2 
3 #include <iostream>
4 
5 void Topology::addBoard(const std::string& path, const std::string& boardType,
6                         const std::string& boardName,
7                         const nlohmann::json& exposesItem)
8 {
9     auto findType = exposesItem.find("Type");
10     if (findType == exposesItem.end())
11     {
12         return;
13     }
14 
15     boardNames.try_emplace(boardName, path);
16 
17     PortType exposesType = findType->get<std::string>();
18 
19     if (exposesType == "DownstreamPort")
20     {
21         auto findConnectsTo = exposesItem.find("ConnectsToType");
22         if (findConnectsTo == exposesItem.end())
23         {
24             std::cerr << "Board at path " << path
25                       << " is missing ConnectsToType" << std::endl;
26             return;
27         }
28         PortType connectsTo = findConnectsTo->get<std::string>();
29 
30         downstreamPorts[connectsTo].emplace_back(path);
31         boardTypes[path] = boardType;
32     }
33     else if (exposesType.ends_with("Port"))
34     {
35         upstreamPorts[exposesType].emplace_back(path);
36         boardTypes[path] = boardType;
37     }
38 }
39 
40 std::unordered_map<std::string, std::vector<Association>>
41     Topology::getAssocs(const std::map<Path, BoardName>& boards)
42 {
43     std::unordered_map<std::string, std::vector<Association>> result;
44 
45     // look at each upstream port type
46     for (const auto& upstreamPortPair : upstreamPorts)
47     {
48         auto downstreamMatch = downstreamPorts.find(upstreamPortPair.first);
49 
50         if (downstreamMatch == downstreamPorts.end())
51         {
52             // no match
53             continue;
54         }
55 
56         for (const Path& upstream : upstreamPortPair.second)
57         {
58             if (boardTypes[upstream] == "Chassis" ||
59                 boardTypes[upstream] == "Board")
60             {
61                 for (const Path& downstream : downstreamMatch->second)
62                 {
63                     // The downstream path must be one we care about.
64                     if (boards.find(downstream) != boards.end())
65                     {
66                         result[downstream].emplace_back("contained_by",
67                                                         "containing", upstream);
68                     }
69                 }
70             }
71         }
72     }
73 
74     return result;
75 }
76 
77 void Topology::remove(const std::string& boardName)
78 {
79     // Remove the board from boardNames, and then using the path
80     // found in boardNames remove it from upstreamPorts and
81     // downstreamPorts.
82     auto boardFind = boardNames.find(boardName);
83     if (boardFind == boardNames.end())
84     {
85         return;
86     }
87 
88     std::string boardPath = boardFind->second;
89 
90     boardNames.erase(boardFind);
91 
92     for (auto it = upstreamPorts.begin(); it != upstreamPorts.end();)
93     {
94         auto pathIt = std::find(it->second.begin(), it->second.end(),
95                                 boardPath);
96         if (pathIt != it->second.end())
97         {
98             it->second.erase(pathIt);
99         }
100 
101         if (it->second.empty())
102         {
103             it = upstreamPorts.erase(it);
104         }
105         else
106         {
107             ++it;
108         }
109     }
110 
111     for (auto it = downstreamPorts.begin(); it != downstreamPorts.end();)
112     {
113         auto pathIt = std::find(it->second.begin(), it->second.end(),
114                                 boardPath);
115         if (pathIt != it->second.end())
116         {
117             it->second.erase(pathIt);
118         }
119 
120         if (it->second.empty())
121         {
122             it = downstreamPorts.erase(it);
123         }
124         else
125         {
126             ++it;
127         }
128     }
129 }
130