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