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