blob: d81bf76f896663f21d9773a2214bed49cc450846 [file] [log] [blame]
Tom Josephbe703f72017-03-09 12:34:35 +05301#include "utils.hpp"
Ratan Guptacc8feb42017-07-25 21:52:10 +05302#include <phosphor-logging/log.hpp>
3#include <phosphor-logging/elog-errors.hpp>
4#include "xyz/openbmc_project/Common/error.hpp"
Tom Josephbe703f72017-03-09 12:34:35 +05305
Ratan Guptab8e99552017-07-27 07:07:48 +05306#include <arpa/inet.h>
7#include <dirent.h>
8#include <net/if.h>
9
Tom Josephbe703f72017-03-09 12:34:35 +053010namespace ipmi
11{
12
Ratan Guptacc8feb42017-07-25 21:52:10 +053013using namespace phosphor::logging;
14using namespace sdbusplus::xyz::openbmc_project::Common::Error;
15
Ratan Guptacc8feb42017-07-25 21:52:10 +053016
17//TODO There may be cases where an interface is implemented by multiple
18// objects,to handle such cases we are interested on that object
19// which are on interested busname.
20// Currently mapper doesn't give the readable busname(gives busid) so we can't
21// use busname to find the object,will do later once the support is there.
22
Ratan Gupta01d4bd12017-08-07 15:53:25 +053023DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus,
24 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +053025 const std::string& serviceRoot,
26 const std::string& match)
27{
28 std::vector<DbusInterface> interfaces;
29 interfaces.emplace_back(interface);
30
Ratan Guptacc8feb42017-07-25 21:52:10 +053031 auto depth = 0;
32
33 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME,
34 MAPPER_OBJ,
35 MAPPER_INTF,
36 "GetSubTree");
37
38 mapperCall.append(serviceRoot, depth, interfaces);
39
40 auto mapperReply = bus.call(mapperCall);
41 if (mapperReply.is_method_error())
42 {
43 log<level::ERR>("Error in mapper call");
44 elog<InternalFailure>();
45 }
46
47 ObjectTree objectTree;
48 mapperReply.read(objectTree);
49
50 if (objectTree.empty())
51 {
52 log<level::ERR>("No Object has impelmented the interface",
53 entry("INTERFACE=%s", interface.c_str()));
54 elog<InternalFailure>();
55 }
56
57 DbusObjectInfo objectInfo;
58
59 // if match is empty then return the first object
60 if(match == "")
61 {
62 objectInfo = std::make_pair(objectTree.begin()->first,
63 std::move(objectTree.begin()->second.begin()->first));
64 return objectInfo;
65 }
66
67 // else search the match string in the object path
68 auto objectFound = false;
69 for (auto& object : objectTree)
70 {
71 if(object.first.find(match) != std::string::npos)
72 {
73 objectFound = true;
74 objectInfo = make_pair(object.first,
75 std::move(object.second.begin()->first));
76 break;
77 }
78 }
79
80 if(!objectFound)
81 {
82 log<level::ERR>("Failed to find object which matches",
83 entry("MATCH=%s", match.c_str()));
84 elog<InternalFailure>();
85 }
86 return objectInfo;
87
88}
89
Ratan Gupta01d4bd12017-08-07 15:53:25 +053090Value getDbusProperty(sdbusplus::bus::bus& bus,
91 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +053092 const std::string& objPath,
93 const std::string& interface,
94 const std::string& property)
95{
96
97 Value value;
98
Ratan Guptacc8feb42017-07-25 21:52:10 +053099 auto method = bus.new_method_call(
100 service.c_str(),
101 objPath.c_str(),
102 PROP_INTF,
103 METHOD_GET);
104
105 method.append(interface, property);
106
107 auto reply = bus.call(method);
108
109 if (reply.is_method_error())
110 {
111 log<level::ERR>("Failed to get property",
112 entry("PROPERTY=%s", property.c_str()),
113 entry("PATH=%s", objPath.c_str()),
114 entry("INTERFACE=%s", interface.c_str()));
115 elog<InternalFailure>();
116 }
117
118 reply.read(value);
119
120 return value;
121}
122
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530123PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
124 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530125 const std::string& objPath,
126 const std::string& interface)
127{
128 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530129
130 auto method = bus.new_method_call(
131 service.c_str(),
132 objPath.c_str(),
133 PROP_INTF,
134 METHOD_GET_ALL);
135
136 method.append(interface);
137
138 auto reply = bus.call(method);
139
140 if (reply.is_method_error())
141 {
142 log<level::ERR>("Failed to get all properties",
143 entry("PATH=%s", objPath.c_str()),
144 entry("INTERFACE=%s", interface.c_str()));
145 elog<InternalFailure>();
146 }
147
148 reply.read(properties);
149 return properties;
150}
151
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530152void setDbusProperty(sdbusplus::bus::bus& bus,
153 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530154 const std::string& objPath,
155 const std::string& interface,
156 const std::string& property,
157 const Value& value)
158{
Ratan Guptacc8feb42017-07-25 21:52:10 +0530159 auto method = bus.new_method_call(
160 service.c_str(),
161 objPath.c_str(),
162 PROP_INTF,
163 METHOD_SET);
164
165 method.append(interface, property, value);
166
167 if (!bus.call(method))
168 {
169 log<level::ERR>("Failed to set property",
170 entry("PROPERTY=%s", property.c_str()),
171 entry("PATH=%s",objPath.c_str()),
172 entry("INTERFACE=%s",interface.c_str()));
173 elog<InternalFailure>();
174 }
175
176}
177
178
Tom Josephbe703f72017-03-09 12:34:35 +0530179std::string getService(sdbusplus::bus::bus& bus,
180 const std::string& intf,
181 const std::string& path)
182{
183 auto mapperCall = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
Leonel Gonzalezd15e6c92017-03-16 13:47:58 -0500184 "/xyz/openbmc_project/object_mapper",
Tom Josephbe703f72017-03-09 12:34:35 +0530185 "xyz.openbmc_project.ObjectMapper",
186 "GetObject");
187
188 mapperCall.append(path);
189 mapperCall.append(std::vector<std::string>({intf}));
190
191 auto mapperResponseMsg = bus.call(mapperCall);
192
193 if (mapperResponseMsg.is_method_error())
194 {
195 throw std::runtime_error("ERROR in mapper call");
196 }
197
198 std::map<std::string, std::vector<std::string>> mapperResponse;
199 mapperResponseMsg.read(mapperResponse);
200
201 if (mapperResponse.begin() == mapperResponse.end())
202 {
203 throw std::runtime_error("ERROR in reading the mapper response");
204 }
205
206 return mapperResponse.begin()->first;
207}
208
Ratan Guptab8e99552017-07-27 07:07:48 +0530209ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus,
210 const std::string& serviceRoot,
211 const std::string& interface,
212 const std::string& match)
213{
214 std::vector<std::string> interfaces;
215 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530216
Ratan Guptab8e99552017-07-27 07:07:48 +0530217 auto depth = 0;
218
219 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME,
220 MAPPER_OBJ,
221 MAPPER_INTF,
222 "GetSubTree");
223
224 mapperCall.append(serviceRoot, depth, interfaces);
225
226 auto mapperReply = bus.call(mapperCall);
227 if (mapperReply.is_method_error())
228 {
229 log<level::ERR>("Error in mapper call",
230 entry("SERVICEROOT=%s",serviceRoot.c_str()),
231 entry("INTERFACE=%s", interface.c_str()));
232
233 elog<InternalFailure>();
234 }
235
236 ObjectTree objectTree;
237 mapperReply.read(objectTree);
238
239 for (auto it = objectTree.begin(); it != objectTree.end();)
240 {
241 if (it->first.find(match) == std::string::npos)
242 {
243 it = objectTree.erase(it);
244 }
245 else
246 {
247 ++it;
248 }
249 }
250
251 return objectTree;
252}
253
254void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
255 const std::string& serviceRoot,
256 const std::string& interface,
257 const std::string& match)
258{
259 try
260 {
261 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
262
263 for (auto& object : objectTree)
264 {
265 method_no_args::callDbusMethod(bus,
266 object.second.begin()->first,
267 object.first,
268 DELETE_INTERFACE, "Delete");
269 }
270 }
271 catch (InternalFailure& e)
272 {
273 log<level::INFO>("Unable to delete the objects having",
274 entry("INTERFACE=%s", interface.c_str()),
275 entry("SERVICE=%s", serviceRoot.c_str()));
276 }
277}
278
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530279ObjectTree getAllAncestors(sdbusplus::bus::bus& bus,
280 const std::string& path,
281 InterfaceList&& interfaces)
282{
283 auto convertToString = [](InterfaceList& interfaces) -> std::string
284 {
285 std::string intfStr;
286 for (const auto& intf : interfaces)
287 {
288 intfStr += "," + intf;
289 }
290 return intfStr;
291 };
292
293 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME,
294 MAPPER_OBJ,
295 MAPPER_INTF,
296 "GetAncestors");
297 mapperCall.append(path, interfaces);
298
299 auto mapperReply = bus.call(mapperCall);
300 if (mapperReply.is_method_error())
301 {
302 log<level::ERR>("Error in mapper call",
303 entry("PATH=%s", path.c_str()),
304 entry("INTERFACES=%s",
305 convertToString(interfaces).c_str()));
306
307 elog<InternalFailure>();
308 }
309
310 ObjectTree objectTree;
311 mapperReply.read(objectTree);
312
313 if (objectTree.empty())
314 {
315 log<level::ERR>("No Object has impelmented the interface",
316 entry("PATH=%s", path.c_str()),
317 entry("INTERFACES=%s",
318 convertToString(interfaces).c_str()));
319 elog<InternalFailure>();
320 }
321
322 return objectTree;
323}
Ratan Guptab8e99552017-07-27 07:07:48 +0530324
325namespace method_no_args
326{
327
328void callDbusMethod(sdbusplus::bus::bus& bus,
329 const std::string& service,
330 const std::string& objPath,
331 const std::string& interface,
332 const std::string& method)
333
334{
335 auto busMethod = bus.new_method_call(
336 service.c_str(),
337 objPath.c_str(),
338 interface.c_str(),
339 method.c_str());
340
341 auto reply = bus.call(busMethod);
342
343 if (reply.is_method_error())
344 {
345 log<level::ERR>("Failed to execute method",
346 entry("METHOD=%s", method.c_str()),
347 entry("PATH=%s", objPath.c_str()),
348 entry("INTERFACE=%s", interface.c_str()));
349 elog<InternalFailure>();
350 }
351}
352
353}// namespace method_no_args
354
355namespace network
356{
357
358void createIP(sdbusplus::bus::bus& bus,
359 const std::string& service,
360 const std::string& objPath,
361 const std::string& protocolType,
362 const std::string& ipaddress,
363 uint8_t prefix)
364{
365 std::string gateway = "";
366
367 auto busMethod = bus.new_method_call(
368 service.c_str(),
369 objPath.c_str(),
370 IP_CREATE_INTERFACE,
371 "IP");
372
373 busMethod.append(protocolType, ipaddress, prefix, gateway);
374
375 auto reply = bus.call(busMethod);
376
377 if (reply.is_method_error())
378 {
379 log<level::ERR>("Failed to excute method",
380 entry("METHOD=%s", "IP"),
381 entry("PATH=%s", objPath.c_str()));
382 elog<InternalFailure>();
383 }
384
385}
386
Ratan Gupta533d03b2017-07-30 10:39:22 +0530387void createVLAN(sdbusplus::bus::bus& bus,
388 const std::string& service,
389 const std::string& objPath,
390 const std::string& interfaceName,
391 uint32_t vlanID)
392{
393 auto busMethod = bus.new_method_call(
394 service.c_str(),
395 objPath.c_str(),
396 VLAN_CREATE_INTERFACE,
397 "VLAN");
398
399 busMethod.append(interfaceName, vlanID);
400
401 auto reply = bus.call(busMethod);
402
403 if (reply.is_method_error())
404 {
405 log<level::ERR>("Failed to excute method",
406 entry("METHOD=%s", "VLAN"),
407 entry("PATH=%s", objPath.c_str()));
408 elog<InternalFailure>();
409 }
410
411}
412
Ratan Guptab8e99552017-07-27 07:07:48 +0530413uint8_t toPrefix(int addressFamily, const std::string& subnetMask)
414{
415 if (addressFamily == AF_INET6)
416 {
417 return 0;
418 }
419
420 uint32_t buff {};
421
422 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
423 if (rc <= 0)
424 {
425 log<level::ERR>("inet_pton failed:",
426 entry("SUBNETMASK=%s", subnetMask));
427 return 0;
428 }
429
430 buff = be32toh(buff);
431 // total no of bits - total no of leading zero == total no of ones
432 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
433 {
434 return __builtin_popcount(buff);
435 }
436 else
437 {
438 log<level::ERR>("Invalid Mask",
439 entry("SUBNETMASK=%s", subnetMask));
440 return 0;
441 }
442}
443
Ratan Gupta533d03b2017-07-30 10:39:22 +0530444uint32_t getVLAN(const std::string& path)
445{
446 // Path would be look like
447 // /xyz/openbmc_project/network/eth0_443/ipv4
448
449 uint32_t vlanID = 0;
450 try
451 {
452 auto intfObjectPath = path.substr(0,
453 path.find(IP_TYPE) - 1);
454
455 auto intfName = intfObjectPath.substr(intfObjectPath.rfind("/") + 1);
456
457 auto index = intfName.find("_");
458 if (index != std::string::npos)
459 {
460 auto str = intfName.substr(index + 1);
461 vlanID = std::stoul(str);
462 }
463 }
464 catch (std::exception & e)
465 {
466 log<level::ERR>("Exception occured during getVLAN",
467 entry("PATH=%s",path.c_str()),
468 entry("EXCEPTIOn=%s", e.what()));
469 }
470 return vlanID;
471}
472
Ratan Guptab8e99552017-07-27 07:07:48 +0530473} // namespace network
Tom Josephbe703f72017-03-09 12:34:35 +0530474} // namespace ipmi