1 #include "hyp_network_manager.hpp"
2 
3 #include "types.hpp"
4 #include "util.hpp"
5 
6 #include <phosphor-logging/elog-errors.hpp>
7 #include <phosphor-logging/elog.hpp>
8 #include <phosphor-logging/log.hpp>
9 #include <sdbusplus/bus.hpp>
10 #include <sdbusplus/server/object.hpp>
11 #include <xyz/openbmc_project/Common/error.hpp>
12 
13 using sdbusplus::exception::SdBusError;
14 
15 class HypNetworkMgr;
16 
17 namespace phosphor
18 {
19 namespace network
20 {
21 using namespace phosphor::logging;
22 using InternalFailure =
23     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24 
25 const std::string intType = "Integer";
26 const std::string strType = "String";
27 const std::string enumType = "Enumeration";
28 
29 using ObjectTree =
30     std::map<std::string, std::map<std::string, std::vector<std::string>>>;
31 
32 auto HypNetworkMgr::getDBusProp(const std::string& objectName,
33                                 const std::string& interface,
34                                 const std::string& kw)
35 {
36     auto bus = sdbusplus::bus::new_default();
37     auto properties = bus.new_method_call(
38         "xyz.openbmc_project.BIOSConfigManager", objectName.c_str(),
39         "org.freedesktop.DBus.Properties", "Get");
40     properties.append(interface);
41     properties.append(kw);
42     auto result = bus.call(properties);
43 
44     if (result.is_method_error())
45     {
46         throw std::runtime_error("Get api failed");
47     }
48     return result;
49 }
50 
51 void HypNetworkMgr::setBIOSTableAttr(
52     std::string attrName, std::variant<std::string, int64_t> attrValue,
53     std::string attrType)
54 {
55     auto findAttr = biosTableAttrs.find(attrName);
56     if (findAttr != biosTableAttrs.end())
57     {
58         if (attrType == intType)
59         {
60             int64_t value = std::get<int64_t>(attrValue);
61             if (value != std::get<int64_t>(findAttr->second))
62             {
63                 biosTableAttrs.erase(findAttr);
64                 biosTableAttrs.emplace(attrName, value);
65             }
66         }
67         else if (attrType == strType)
68         {
69             std::string value = std::get<std::string>(attrValue);
70             if (value != std::get<std::string>(findAttr->second))
71             {
72                 biosTableAttrs.erase(findAttr);
73                 biosTableAttrs.emplace(attrName, value);
74             }
75         }
76     }
77     else
78     {
79         log<level::INFO>(
80             "setBIOSTableAttr: Attribute is not found in biosTableAttrs"),
81             entry("attrName : ", attrName.c_str());
82     }
83 }
84 
85 void HypNetworkMgr::setDefaultBIOSTableAttrsOnIntf(const std::string& intf)
86 {
87     biosTableAttrs.emplace("vmi_" + intf + "_ipv4_ipaddr", "0.0.0.0");
88     biosTableAttrs.emplace("vmi_" + intf + "_ipv4_gateway", "0.0.0.0");
89     biosTableAttrs.emplace("vmi_" + intf + "_ipv4_prefix_length", 0);
90     biosTableAttrs.emplace("vmi_" + intf + "_ipv4_method", "IPv4Static");
91 }
92 
93 void HypNetworkMgr::setDefaultHostnameInBIOSTableAttrs()
94 {
95     biosTableAttrs.emplace("vmi_hostname", "");
96 }
97 
98 void HypNetworkMgr::setBIOSTableAttrs()
99 {
100     try
101     {
102         constexpr auto biosMgrIntf = "xyz.openbmc_project.BIOSConfig.Manager";
103         constexpr auto biosMgrObj = "/xyz/openbmc_project/bios_config";
104 
105         constexpr auto mapperBus = "xyz.openbmc_project.ObjectMapper";
106         constexpr auto mapperObj = "/xyz/openbmc_project/object_mapper";
107         constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
108 
109         std::vector<std::string> interfaces;
110         interfaces.emplace_back(biosMgrIntf);
111         auto depth = 0;
112 
113         auto mapperCall =
114             bus.new_method_call(mapperBus, mapperObj, mapperIntf, "GetSubTree");
115 
116         mapperCall.append(biosMgrObj, depth, interfaces);
117 
118         auto mapperReply = bus.call(mapperCall);
119         if (mapperReply.is_method_error())
120         {
121             log<level::ERR>("Error in mapper call");
122             elog<InternalFailure>();
123         }
124 
125         ObjectTree objectTree;
126         mapperReply.read(objectTree);
127 
128         if (objectTree.empty())
129         {
130             log<level::ERR>("No Object has implemented the interface",
131                             entry("INTERFACE=%s", biosMgrIntf));
132             elog<InternalFailure>();
133         }
134 
135         std::string objPath;
136 
137         if (1 == objectTree.size())
138         {
139             objPath = objectTree.begin()->first;
140         }
141         else
142         {
143             // If there are more than 2 objects, object path must contain the
144             // interface name
145             for (auto const& object : objectTree)
146             {
147                 log<level::INFO>("interface", entry("INT=%s", biosMgrIntf));
148                 log<level::INFO>("object",
149                                  entry("OBJ=%s", object.first.c_str()));
150 
151                 if (std::string::npos != object.first.find(biosMgrIntf))
152                 {
153                     objPath = object.first;
154                     break;
155                 }
156             }
157 
158             if (objPath.empty())
159             {
160                 log<level::ERR>("Can't find the object for the interface",
161                                 entry("intfName=%s", biosMgrIntf));
162                 elog<InternalFailure>();
163             }
164         }
165 
166         std::variant<BiosBaseTableType> response;
167         getDBusProp(objPath, biosMgrIntf, "BaseBIOSTable").read(response);
168 
169         const BiosBaseTableType* baseBiosTable =
170             std::get_if<BiosBaseTableType>(&response);
171 
172         if (baseBiosTable == nullptr)
173         {
174             log<level::ERR>("BaseBiosTable is empty. No attributes found!");
175             return;
176         }
177 
178         for (const BiosBaseTableItemType& item : *baseBiosTable)
179         {
180             if (item.first.rfind("vmi", 0) == 0) // starts with the prefix
181             {
182                 const std::string& itemType =
183                     std::get<biosBaseAttrType>(item.second);
184 
185                 if (itemType.compare(itemType.size() - intType.size(),
186                                      intType.size(), intType) == 0)
187                 {
188                     const int64_t* currValue = std::get_if<int64_t>(
189                         &std::get<biosBaseCurrValue>(item.second));
190                     if (currValue != nullptr)
191                     {
192                         biosTableAttrs.emplace(item.first, *currValue);
193                     }
194                 }
195                 else if ((itemType.compare(itemType.size() - strType.size(),
196                                            strType.size(), strType) == 0) ||
197                          (itemType.compare(itemType.size() - enumType.size(),
198                                            enumType.size(), enumType) == 0))
199                 {
200                     const std::string* currValue = std::get_if<std::string>(
201                         &std::get<biosBaseCurrValue>(item.second));
202                     if (currValue != nullptr)
203                     {
204                         biosTableAttrs.emplace(item.first, *currValue);
205                     }
206                 }
207                 else
208                 {
209                     log<level::ERR>("Unsupported datatype: The attribute is of "
210                                     "unknown type");
211                 }
212             }
213         }
214     }
215     catch (const SdBusError& e)
216     {
217         log<level::ERR>("Error in making dbus call");
218         throw std::runtime_error("DBus call failed");
219     }
220 }
221 
222 biosTableType HypNetworkMgr::getBIOSTableAttrs()
223 {
224     return biosTableAttrs;
225 }
226 
227 void HypNetworkMgr::createIfObjects()
228 {
229     setBIOSTableAttrs();
230 
231     if ((getBIOSTableAttrs()).size() == 0)
232     {
233         setDefaultHostnameInBIOSTableAttrs();
234     }
235 
236     // The hypervisor can support maximum of
237     // 2 ethernet interfaces. Both eth0/1 objects are
238     // created during init time to support the static
239     // network configurations on the both.
240     // create eth0 and eth1 objects
241     log<level::INFO>("Create eth0 and eth1 objects");
242 }
243 
244 void HypNetworkMgr::createSysConfObj()
245 {
246     systemConf.reset(nullptr);
247     this->systemConf = std::make_unique<phosphor::network::HypSysConfig>(
248         bus, objectPath + "/config", *this);
249 }
250 
251 } // namespace network
252 } // namespace phosphor
253