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