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