xref: /openbmc/entity-manager/src/topology.cpp (revision b7077437)
1 #include "topology.hpp"
2 
3 #include <iostream>
4 
addBoard(const std::string & path,const std::string & boardType,const std::string & boardName,const nlohmann::json & exposesItem)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         auto findPoweredBy = exposesItem.find("PowerPort");
33         if (findPoweredBy != exposesItem.end())
34         {
35             powerPaths.insert(path);
36         }
37     }
38     else if (exposesType.ends_with("Port"))
39     {
40         upstreamPorts[exposesType].emplace_back(path);
41         boardTypes[path] = boardType;
42     }
43 }
44 
45 std::unordered_map<std::string, std::vector<Association>>
getAssocs(const std::map<Path,BoardName> & boards)46     Topology::getAssocs(const std::map<Path, BoardName>& boards)
47 {
48     std::unordered_map<std::string, std::vector<Association>> result;
49 
50     // look at each upstream port type
51     for (const auto& upstreamPortPair : upstreamPorts)
52     {
53         auto downstreamMatch = downstreamPorts.find(upstreamPortPair.first);
54 
55         if (downstreamMatch == downstreamPorts.end())
56         {
57             // no match
58             continue;
59         }
60 
61         for (const Path& upstream : upstreamPortPair.second)
62         {
63             if (boardTypes[upstream] == "Chassis" ||
64                 boardTypes[upstream] == "Board")
65             {
66                 for (const Path& downstream : downstreamMatch->second)
67                 {
68                     // The downstream path must be one we care about.
69                     if (boards.find(downstream) != boards.end())
70                     {
71                         result[downstream].emplace_back("contained_by",
72                                                         "containing", upstream);
73                         if (powerPaths.find(downstream) != powerPaths.end())
74                         {
75                             result[upstream].emplace_back(
76                                 "powered_by", "powering", downstream);
77                         }
78                     }
79                 }
80             }
81         }
82     }
83 
84     return result;
85 }
86 
remove(const std::string & boardName)87 void Topology::remove(const std::string& boardName)
88 {
89     // Remove the board from boardNames, and then using the path
90     // found in boardNames remove it from upstreamPorts and
91     // downstreamPorts.
92     auto boardFind = boardNames.find(boardName);
93     if (boardFind == boardNames.end())
94     {
95         return;
96     }
97 
98     std::string boardPath = boardFind->second;
99 
100     boardNames.erase(boardFind);
101 
102     for (auto it = upstreamPorts.begin(); it != upstreamPorts.end();)
103     {
104         auto pathIt =
105             std::find(it->second.begin(), it->second.end(), boardPath);
106         if (pathIt != it->second.end())
107         {
108             it->second.erase(pathIt);
109         }
110 
111         if (it->second.empty())
112         {
113             it = upstreamPorts.erase(it);
114         }
115         else
116         {
117             ++it;
118         }
119     }
120 
121     for (auto it = downstreamPorts.begin(); it != downstreamPorts.end();)
122     {
123         auto pathIt =
124             std::find(it->second.begin(), it->second.end(), boardPath);
125         if (pathIt != it->second.end())
126         {
127             it->second.erase(pathIt);
128         }
129 
130         if (it->second.empty())
131         {
132             it = downstreamPorts.erase(it);
133         }
134         else
135         {
136             ++it;
137         }
138     }
139 }
140