blob: 2e6c5e7d4920d4517a669e36e868f4899b7dffe0 [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
279
280namespace method_no_args
281{
282
283void callDbusMethod(sdbusplus::bus::bus& bus,
284 const std::string& service,
285 const std::string& objPath,
286 const std::string& interface,
287 const std::string& method)
288
289{
290 auto busMethod = bus.new_method_call(
291 service.c_str(),
292 objPath.c_str(),
293 interface.c_str(),
294 method.c_str());
295
296 auto reply = bus.call(busMethod);
297
298 if (reply.is_method_error())
299 {
300 log<level::ERR>("Failed to execute method",
301 entry("METHOD=%s", method.c_str()),
302 entry("PATH=%s", objPath.c_str()),
303 entry("INTERFACE=%s", interface.c_str()));
304 elog<InternalFailure>();
305 }
306}
307
308}// namespace method_no_args
309
310namespace network
311{
312
313void createIP(sdbusplus::bus::bus& bus,
314 const std::string& service,
315 const std::string& objPath,
316 const std::string& protocolType,
317 const std::string& ipaddress,
318 uint8_t prefix)
319{
320 std::string gateway = "";
321
322 auto busMethod = bus.new_method_call(
323 service.c_str(),
324 objPath.c_str(),
325 IP_CREATE_INTERFACE,
326 "IP");
327
328 busMethod.append(protocolType, ipaddress, prefix, gateway);
329
330 auto reply = bus.call(busMethod);
331
332 if (reply.is_method_error())
333 {
334 log<level::ERR>("Failed to excute method",
335 entry("METHOD=%s", "IP"),
336 entry("PATH=%s", objPath.c_str()));
337 elog<InternalFailure>();
338 }
339
340}
341
Ratan Gupta533d03b2017-07-30 10:39:22 +0530342void createVLAN(sdbusplus::bus::bus& bus,
343 const std::string& service,
344 const std::string& objPath,
345 const std::string& interfaceName,
346 uint32_t vlanID)
347{
348 auto busMethod = bus.new_method_call(
349 service.c_str(),
350 objPath.c_str(),
351 VLAN_CREATE_INTERFACE,
352 "VLAN");
353
354 busMethod.append(interfaceName, vlanID);
355
356 auto reply = bus.call(busMethod);
357
358 if (reply.is_method_error())
359 {
360 log<level::ERR>("Failed to excute method",
361 entry("METHOD=%s", "VLAN"),
362 entry("PATH=%s", objPath.c_str()));
363 elog<InternalFailure>();
364 }
365
366}
367
Ratan Guptab8e99552017-07-27 07:07:48 +0530368uint8_t toPrefix(int addressFamily, const std::string& subnetMask)
369{
370 if (addressFamily == AF_INET6)
371 {
372 return 0;
373 }
374
375 uint32_t buff {};
376
377 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
378 if (rc <= 0)
379 {
380 log<level::ERR>("inet_pton failed:",
381 entry("SUBNETMASK=%s", subnetMask));
382 return 0;
383 }
384
385 buff = be32toh(buff);
386 // total no of bits - total no of leading zero == total no of ones
387 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
388 {
389 return __builtin_popcount(buff);
390 }
391 else
392 {
393 log<level::ERR>("Invalid Mask",
394 entry("SUBNETMASK=%s", subnetMask));
395 return 0;
396 }
397}
398
Ratan Gupta533d03b2017-07-30 10:39:22 +0530399uint32_t getVLAN(const std::string& path)
400{
401 // Path would be look like
402 // /xyz/openbmc_project/network/eth0_443/ipv4
403
404 uint32_t vlanID = 0;
405 try
406 {
407 auto intfObjectPath = path.substr(0,
408 path.find(IP_TYPE) - 1);
409
410 auto intfName = intfObjectPath.substr(intfObjectPath.rfind("/") + 1);
411
412 auto index = intfName.find("_");
413 if (index != std::string::npos)
414 {
415 auto str = intfName.substr(index + 1);
416 vlanID = std::stoul(str);
417 }
418 }
419 catch (std::exception & e)
420 {
421 log<level::ERR>("Exception occured during getVLAN",
422 entry("PATH=%s",path.c_str()),
423 entry("EXCEPTIOn=%s", e.what()));
424 }
425 return vlanID;
426}
427
Ratan Guptab8e99552017-07-27 07:07:48 +0530428} // namespace network
Tom Josephbe703f72017-03-09 12:34:35 +0530429} // namespace ipmi