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