blob: cc4b763d6b65abd22330d3e21e70ebf2f89ca937 [file] [log] [blame]
Ratan Guptab8e99552017-07-27 07:07:48 +05301#include <arpa/inet.h>
2#include <dirent.h>
Yong Li7dc4ac02019-08-23 17:44:32 +08003#include <fcntl.h>
4#include <linux/i2c-dev.h>
5#include <linux/i2c.h>
Ratan Guptab8e99552017-07-27 07:07:48 +05306#include <net/if.h>
Yong Li7dc4ac02019-08-23 17:44:32 +08007#include <sys/ioctl.h>
8#include <sys/types.h>
9#include <unistd.h>
Ratan Guptab8e99552017-07-27 07:07:48 +053010
Patrick Venture2e633522018-10-13 13:51:06 -070011#include <algorithm>
Kun Yi5dcf41e2019-03-05 14:02:51 -080012#include <chrono>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070013#include <ipmid/utils.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070014#include <phosphor-logging/elog-errors.hpp>
15#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070016#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070017#include <xyz/openbmc_project/Common/error.hpp>
18
Tom Josephbe703f72017-03-09 12:34:35 +053019namespace ipmi
20{
21
Ratan Guptacc8feb42017-07-25 21:52:10 +053022using namespace phosphor::logging;
23using namespace sdbusplus::xyz::openbmc_project::Common::Error;
24
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050025namespace network
26{
27
28/** @brief checks if the given ip is Link Local Ip or not.
Patrick Venture0b02be92018-08-31 11:55:55 -070029 * @param[in] ipaddress - IPAddress.
30 */
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050031bool isLinkLocalIP(const std::string& ipaddress);
32
Patrick Venture0b02be92018-08-31 11:55:55 -070033} // namespace network
Ratan Guptacc8feb42017-07-25 21:52:10 +053034
Patrick Venture0b02be92018-08-31 11:55:55 -070035// TODO There may be cases where an interface is implemented by multiple
Ratan Guptacc8feb42017-07-25 21:52:10 +053036// objects,to handle such cases we are interested on that object
37// which are on interested busname.
38// Currently mapper doesn't give the readable busname(gives busid) so we can't
39// use busname to find the object,will do later once the support is there.
40
Ratan Gupta01d4bd12017-08-07 15:53:25 +053041DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus,
42 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +053043 const std::string& serviceRoot,
44 const std::string& match)
45{
46 std::vector<DbusInterface> interfaces;
47 interfaces.emplace_back(interface);
48
Ratan Guptacc8feb42017-07-25 21:52:10 +053049 auto depth = 0;
50
Patrick Venture0b02be92018-08-31 11:55:55 -070051 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
52 MAPPER_INTF, "GetSubTree");
Ratan Guptacc8feb42017-07-25 21:52:10 +053053
54 mapperCall.append(serviceRoot, depth, interfaces);
55
56 auto mapperReply = bus.call(mapperCall);
57 if (mapperReply.is_method_error())
58 {
59 log<level::ERR>("Error in mapper call");
60 elog<InternalFailure>();
61 }
62
63 ObjectTree objectTree;
64 mapperReply.read(objectTree);
65
66 if (objectTree.empty())
67 {
Patrick Venturef0c48782017-09-21 18:48:51 -070068 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053069 entry("INTERFACE=%s", interface.c_str()));
70 elog<InternalFailure>();
71 }
72
73 DbusObjectInfo objectInfo;
74
75 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070076 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053077 {
Patrick Venture0b02be92018-08-31 11:55:55 -070078 objectInfo = std::make_pair(
79 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053080 std::move(objectTree.begin()->second.begin()->first));
81 return objectInfo;
82 }
83
84 // else search the match string in the object path
Patrick Venture2e633522018-10-13 13:51:06 -070085 auto found = std::find_if(
86 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
87 return (object.first.find(match) != std::string::npos);
88 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053089
Patrick Venture2e633522018-10-13 13:51:06 -070090 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053091 {
92 log<level::ERR>("Failed to find object which matches",
93 entry("MATCH=%s", match.c_str()));
94 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070095 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053096 }
Patrick Venture2e633522018-10-13 13:51:06 -070097
98 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053099}
100
Ratan Guptadd646202017-11-21 17:46:59 +0530101DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus,
102 const std::string& interface,
103 const std::string& serviceRoot,
104 const std::string& match)
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500105{
106 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
107
108 if (objectTree.empty())
109 {
110 log<level::ERR>("No Object has implemented the IP interface",
111 entry("INTERFACE=%s", interface.c_str()));
112 elog<InternalFailure>();
113 }
114
Ratan Guptadd646202017-11-21 17:46:59 +0530115 DbusObjectInfo objectInfo;
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500116
117 for (auto& object : objectTree)
118 {
119 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700120 bus, object.second.begin()->first, object.first,
121 ipmi::network::IP_INTERFACE, "Address");
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500122
Patrick Venture0b02be92018-08-31 11:55:55 -0700123 objectInfo = std::make_pair(object.first, object.second.begin()->first);
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500124
125 // if LinkLocalIP found look for Non-LinkLocalIP
Vernon Maueryf442e112019-04-09 11:44:36 -0700126 if (ipmi::network::isLinkLocalIP(std::get<std::string>(variant)))
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500127 {
128 continue;
129 }
130 else
131 {
132 break;
133 }
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500134 }
Ratan Guptadd646202017-11-21 17:46:59 +0530135 return objectInfo;
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500136}
137
Patrick Venture0b02be92018-08-31 11:55:55 -0700138Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
139 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800140 const std::string& property,
141 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530142{
143
144 Value value;
145
Patrick Venture0b02be92018-08-31 11:55:55 -0700146 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
147 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530148
149 method.append(interface, property);
150
Kun Yi5dcf41e2019-03-05 14:02:51 -0800151 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530152
153 if (reply.is_method_error())
154 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700155 log<level::ERR>("Failed to get property",
156 entry("PROPERTY=%s", property.c_str()),
157 entry("PATH=%s", objPath.c_str()),
158 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530159 elog<InternalFailure>();
160 }
161
162 reply.read(value);
163
164 return value;
165}
166
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530167PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
168 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530169 const std::string& objPath,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800170 const std::string& interface,
171 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530172{
173 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530174
Patrick Venture0b02be92018-08-31 11:55:55 -0700175 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
176 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530177
178 method.append(interface);
179
Kun Yi5dcf41e2019-03-05 14:02:51 -0800180 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530181
182 if (reply.is_method_error())
183 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700184 log<level::ERR>("Failed to get all properties",
185 entry("PATH=%s", objPath.c_str()),
186 entry("INTERFACE=%s", interface.c_str()));
187 elog<InternalFailure>();
Ratan Guptacc8feb42017-07-25 21:52:10 +0530188 }
189
190 reply.read(properties);
191 return properties;
192}
193
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600194ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700195 const std::string& service,
196 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600197{
198 ipmi::ObjectValueTree interfaces;
199
Patrick Venture0b02be92018-08-31 11:55:55 -0700200 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
201 "org.freedesktop.DBus.ObjectManager",
202 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600203
204 auto reply = bus.call(method);
205
206 if (reply.is_method_error())
207 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700208 log<level::ERR>("Failed to get managed objects",
209 entry("PATH=%s", objPath.c_str()));
210 elog<InternalFailure>();
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600211 }
212
213 reply.read(interfaces);
214 return interfaces;
215}
216
Patrick Venture0b02be92018-08-31 11:55:55 -0700217void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
218 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800219 const std::string& property, const Value& value,
220 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530221{
Patrick Venture0b02be92018-08-31 11:55:55 -0700222 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
223 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530224
225 method.append(interface, property, value);
226
Kun Yi5dcf41e2019-03-05 14:02:51 -0800227 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530228 {
229 log<level::ERR>("Failed to set property",
230 entry("PROPERTY=%s", property.c_str()),
Patrick Venture0b02be92018-08-31 11:55:55 -0700231 entry("PATH=%s", objPath.c_str()),
232 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530233 elog<InternalFailure>();
234 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530235}
236
Patrick Venture0b02be92018-08-31 11:55:55 -0700237ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800238 intf(intf), path(path), cachedService(std::nullopt),
239 cachedBusName(std::nullopt)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700240{
241}
242
Patrick Venture0b02be92018-08-31 11:55:55 -0700243ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800244 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
245 cachedBusName(std::nullopt)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700246{
247}
248
249const std::string& ServiceCache::getService(sdbusplus::bus::bus& bus)
250{
251 if (!isValid(bus))
252 {
253 cachedBusName = bus.get_unique_name();
254 cachedService = ::ipmi::getService(bus, intf, path);
255 }
256 return cachedService.value();
257}
258
259void ServiceCache::invalidate()
260{
Vernon Mauery54012502018-11-07 10:17:31 -0800261 cachedBusName = std::nullopt;
262 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700263}
264
Patrick Venture0b02be92018-08-31 11:55:55 -0700265sdbusplus::message::message
266 ServiceCache::newMethodCall(sdbusplus::bus::bus& bus, const char* intf,
267 const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700268{
Patrick Venture0b02be92018-08-31 11:55:55 -0700269 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
270 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700271}
272
273bool ServiceCache::isValid(sdbusplus::bus::bus& bus) const
274{
275 return cachedService && cachedBusName == bus.get_unique_name();
276}
277
Patrick Venture0b02be92018-08-31 11:55:55 -0700278std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530279 const std::string& path)
280{
Patrick Venture0b02be92018-08-31 11:55:55 -0700281 auto mapperCall =
282 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
283 "/xyz/openbmc_project/object_mapper",
284 "xyz.openbmc_project.ObjectMapper", "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530285
286 mapperCall.append(path);
287 mapperCall.append(std::vector<std::string>({intf}));
288
289 auto mapperResponseMsg = bus.call(mapperCall);
290
291 if (mapperResponseMsg.is_method_error())
292 {
293 throw std::runtime_error("ERROR in mapper call");
294 }
295
296 std::map<std::string, std::vector<std::string>> mapperResponse;
297 mapperResponseMsg.read(mapperResponse);
298
299 if (mapperResponse.begin() == mapperResponse.end())
300 {
301 throw std::runtime_error("ERROR in reading the mapper response");
302 }
303
304 return mapperResponse.begin()->first;
305}
306
Ratan Guptab8e99552017-07-27 07:07:48 +0530307ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus,
308 const std::string& serviceRoot,
309 const std::string& interface,
310 const std::string& match)
311{
312 std::vector<std::string> interfaces;
313 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530314
Ratan Guptab8e99552017-07-27 07:07:48 +0530315 auto depth = 0;
316
Patrick Venture0b02be92018-08-31 11:55:55 -0700317 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
318 MAPPER_INTF, "GetSubTree");
Ratan Guptab8e99552017-07-27 07:07:48 +0530319
320 mapperCall.append(serviceRoot, depth, interfaces);
321
322 auto mapperReply = bus.call(mapperCall);
323 if (mapperReply.is_method_error())
324 {
325 log<level::ERR>("Error in mapper call",
Patrick Venture0b02be92018-08-31 11:55:55 -0700326 entry("SERVICEROOT=%s", serviceRoot.c_str()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530327 entry("INTERFACE=%s", interface.c_str()));
328
329 elog<InternalFailure>();
330 }
331
332 ObjectTree objectTree;
333 mapperReply.read(objectTree);
334
335 for (auto it = objectTree.begin(); it != objectTree.end();)
336 {
337 if (it->first.find(match) == std::string::npos)
338 {
339 it = objectTree.erase(it);
340 }
341 else
342 {
343 ++it;
344 }
345 }
346
347 return objectTree;
348}
349
350void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
351 const std::string& serviceRoot,
352 const std::string& interface,
353 const std::string& match)
354{
355 try
356 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700357 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530358
359 for (auto& object : objectTree)
360 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700361 method_no_args::callDbusMethod(bus, object.second.begin()->first,
362 object.first, DELETE_INTERFACE,
363 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530364 }
365 }
Vernon Mauery7a614182018-11-27 12:54:52 -0800366 catch (sdbusplus::exception::exception& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530367 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800368 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
369 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530370 entry("INTERFACE=%s", interface.c_str()),
371 entry("SERVICE=%s", serviceRoot.c_str()));
372 }
373}
374
Patrick Venture0b02be92018-08-31 11:55:55 -0700375ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530376 InterfaceList&& interfaces)
377{
Patrick Venture0b02be92018-08-31 11:55:55 -0700378 auto convertToString = [](InterfaceList& interfaces) -> std::string {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530379 std::string intfStr;
380 for (const auto& intf : interfaces)
381 {
382 intfStr += "," + intf;
383 }
384 return intfStr;
385 };
386
Patrick Venture0b02be92018-08-31 11:55:55 -0700387 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
388 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530389 mapperCall.append(path, interfaces);
390
391 auto mapperReply = bus.call(mapperCall);
392 if (mapperReply.is_method_error())
393 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700394 log<level::ERR>(
395 "Error in mapper call", entry("PATH=%s", path.c_str()),
396 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530397
398 elog<InternalFailure>();
399 }
400
401 ObjectTree objectTree;
402 mapperReply.read(objectTree);
403
404 if (objectTree.empty())
405 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700406 log<level::ERR>(
407 "No Object has implemented the interface",
408 entry("PATH=%s", path.c_str()),
409 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530410 elog<InternalFailure>();
411 }
412
413 return objectTree;
414}
Ratan Guptab8e99552017-07-27 07:07:48 +0530415
416namespace method_no_args
417{
418
Patrick Venture0b02be92018-08-31 11:55:55 -0700419void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service,
420 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530421 const std::string& method)
422
423{
Patrick Venture0b02be92018-08-31 11:55:55 -0700424 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
425 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530426
427 auto reply = bus.call(busMethod);
428
429 if (reply.is_method_error())
430 {
431 log<level::ERR>("Failed to execute method",
432 entry("METHOD=%s", method.c_str()),
433 entry("PATH=%s", objPath.c_str()),
434 entry("INTERFACE=%s", interface.c_str()));
435 elog<InternalFailure>();
436 }
437}
438
Patrick Venture0b02be92018-08-31 11:55:55 -0700439} // namespace method_no_args
Ratan Guptab8e99552017-07-27 07:07:48 +0530440
441namespace network
442{
443
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500444bool isLinkLocalIP(const std::string& address)
445{
446 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0;
447}
448
Patrick Venture0b02be92018-08-31 11:55:55 -0700449void createIP(sdbusplus::bus::bus& bus, const std::string& service,
450 const std::string& objPath, const std::string& protocolType,
451 const std::string& ipaddress, uint8_t prefix)
Ratan Guptab8e99552017-07-27 07:07:48 +0530452{
453 std::string gateway = "";
454
Patrick Venture0b02be92018-08-31 11:55:55 -0700455 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
456 IP_CREATE_INTERFACE, "IP");
Ratan Guptab8e99552017-07-27 07:07:48 +0530457
458 busMethod.append(protocolType, ipaddress, prefix, gateway);
459
460 auto reply = bus.call(busMethod);
461
462 if (reply.is_method_error())
463 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700464 log<level::ERR>("Failed to execute method", entry("METHOD=%s", "IP"),
Ratan Guptab8e99552017-07-27 07:07:48 +0530465 entry("PATH=%s", objPath.c_str()));
466 elog<InternalFailure>();
467 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530468}
469
Patrick Venture0b02be92018-08-31 11:55:55 -0700470void createVLAN(sdbusplus::bus::bus& bus, const std::string& service,
471 const std::string& objPath, const std::string& interfaceName,
Ratan Gupta533d03b2017-07-30 10:39:22 +0530472 uint32_t vlanID)
473{
Patrick Venture0b02be92018-08-31 11:55:55 -0700474 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
475 VLAN_CREATE_INTERFACE, "VLAN");
Ratan Gupta533d03b2017-07-30 10:39:22 +0530476
477 busMethod.append(interfaceName, vlanID);
478
479 auto reply = bus.call(busMethod);
480
481 if (reply.is_method_error())
482 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700483 log<level::ERR>("Failed to execute method", entry("METHOD=%s", "VLAN"),
Ratan Gupta533d03b2017-07-30 10:39:22 +0530484 entry("PATH=%s", objPath.c_str()));
485 elog<InternalFailure>();
486 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530487}
488
Ratan Guptab8e99552017-07-27 07:07:48 +0530489uint8_t toPrefix(int addressFamily, const std::string& subnetMask)
490{
491 if (addressFamily == AF_INET6)
492 {
493 return 0;
494 }
495
Patrick Venture0b02be92018-08-31 11:55:55 -0700496 uint32_t buff{};
Ratan Guptab8e99552017-07-27 07:07:48 +0530497
498 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
499 if (rc <= 0)
500 {
501 log<level::ERR>("inet_pton failed:",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -0500502 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Guptab8e99552017-07-27 07:07:48 +0530503 return 0;
504 }
505
506 buff = be32toh(buff);
507 // total no of bits - total no of leading zero == total no of ones
Patrick Venture0b02be92018-08-31 11:55:55 -0700508 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) ==
509 __builtin_popcount(buff))
Ratan Guptab8e99552017-07-27 07:07:48 +0530510 {
511 return __builtin_popcount(buff);
512 }
513 else
514 {
515 log<level::ERR>("Invalid Mask",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -0500516 entry("SUBNETMASK=%s", subnetMask.c_str()));
Ratan Guptab8e99552017-07-27 07:07:48 +0530517 return 0;
518 }
519}
520
Ratan Gupta533d03b2017-07-30 10:39:22 +0530521uint32_t getVLAN(const std::string& path)
522{
523 // Path would be look like
524 // /xyz/openbmc_project/network/eth0_443/ipv4
525
526 uint32_t vlanID = 0;
527 try
528 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700529 auto intfObjectPath = path.substr(0, path.find(IP_TYPE) - 1);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530530
531 auto intfName = intfObjectPath.substr(intfObjectPath.rfind("/") + 1);
532
533 auto index = intfName.find("_");
534 if (index != std::string::npos)
535 {
536 auto str = intfName.substr(index + 1);
537 vlanID = std::stoul(str);
538 }
539 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700540 catch (std::exception& e)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530541 {
Gunnar Mills8991dd62017-10-25 17:11:29 -0500542 log<level::ERR>("Exception occurred during getVLAN",
Patrick Venture0b02be92018-08-31 11:55:55 -0700543 entry("PATH=%s", path.c_str()),
Gunnar Mills5b801e42017-10-19 17:11:42 -0500544 entry("EXCEPTION=%s", e.what()));
Ratan Gupta533d03b2017-07-30 10:39:22 +0530545 }
546 return vlanID;
547}
548
Ratan Guptab8e99552017-07-27 07:07:48 +0530549} // namespace network
Yong Li7dc4ac02019-08-23 17:44:32 +0800550
551ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
552 std::vector<uint8_t> writeData,
553 std::vector<uint8_t>& readBuf)
554{
555 // Open the i2c device, for low-level combined data write/read
556 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
557 if (i2cDev < 0)
558 {
559 log<level::ERR>("Failed to open i2c bus",
560 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
561 return ipmi::ccInvalidFieldRequest;
562 }
563
564 const size_t writeCount = writeData.size();
565 const size_t readCount = readBuf.size();
566 int msgCount = 0;
567 i2c_msg i2cmsg[2] = {0};
568 if (writeCount)
569 {
570 // Data will be writtern to the slave address
571 i2cmsg[msgCount].addr = slaveAddr;
572 i2cmsg[msgCount].flags = 0x00;
573 i2cmsg[msgCount].len = writeCount;
574 i2cmsg[msgCount].buf = writeData.data();
575 msgCount++;
576 }
577 if (readCount)
578 {
579 // Data will be read into the buffer from the slave address
580 i2cmsg[msgCount].addr = slaveAddr;
581 i2cmsg[msgCount].flags = I2C_M_RD;
582 i2cmsg[msgCount].len = readCount;
583 i2cmsg[msgCount].buf = readBuf.data();
584 msgCount++;
585 }
586
587 i2c_rdwr_ioctl_data msgReadWrite = {0};
588 msgReadWrite.msgs = i2cmsg;
589 msgReadWrite.nmsgs = msgCount;
590
591 // Perform the combined write/read
592 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
593 ::close(i2cDev);
594
595 if (ret < 0)
596 {
597 log<level::ERR>("I2C WR Failed!",
598 phosphor::logging::entry("RET=%d", ret));
599 return ipmi::ccUnspecifiedError;
600 }
601 if (readCount)
602 {
603 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
604 }
605
606 return ipmi::ccSuccess;
607}
608
Tom Josephbe703f72017-03-09 12:34:35 +0530609} // namespace ipmi