1 #pragma once 2 3 #include <chrono> 4 #include <ipmid/api-types.hpp> 5 #include <ipmid/types.hpp> 6 #include <optional> 7 #include <sdbusplus/server.hpp> 8 9 namespace ipmi 10 { 11 12 using namespace std::literals::chrono_literals; 13 14 constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper"; 15 constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper"; 16 constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper"; 17 18 constexpr auto ROOT = "/"; 19 constexpr auto HOST_MATCH = "host0"; 20 21 constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties"; 22 constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete"; 23 24 constexpr auto METHOD_GET = "Get"; 25 constexpr auto METHOD_GET_ALL = "GetAll"; 26 constexpr auto METHOD_SET = "Set"; 27 28 /* Use a value of 5s which aligns with BT/KCS bridged timeouts, rather 29 * than the default 25s D-Bus timeout. */ 30 constexpr std::chrono::microseconds IPMI_DBUS_TIMEOUT = 5s; 31 32 /** @class ServiceCache 33 * @brief Caches lookups of service names from the object mapper. 34 * @details Most ipmi commands need to talk to other dbus daemons to perform 35 * their intended actions on the BMC. This usually means they will 36 * first look up the service name providing the interface they 37 * require. This class reduces the number of such calls by caching 38 * the lookup for a specific service. 39 */ 40 class ServiceCache 41 { 42 public: 43 /** @brief Creates a new service cache for the given interface 44 * and path. 45 * 46 * @param[in] intf - The interface used for each lookup 47 * @param[in] path - The path used for each lookup 48 */ 49 ServiceCache(const std::string& intf, const std::string& path); 50 ServiceCache(std::string&& intf, std::string&& path); 51 52 /** @brief Gets the service name from the cache or does in a 53 * lookup when invalid. 54 * 55 * @param[in] bus - The bus associated with and used for looking 56 * up the service. 57 */ 58 const std::string& getService(sdbusplus::bus::bus& bus); 59 60 /** @brief Invalidates the current service name */ 61 void invalidate(); 62 63 /** @brief A wrapper around sdbusplus bus.new_method_call 64 * 65 * @param[in] bus - The bus used for calling the method 66 * @param[in] intf - The interface containing the method 67 * @param[in] method - The method name 68 * @return The message containing the method call. 69 */ 70 sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus, 71 const char* intf, 72 const char* method); 73 74 /** @brief Check to see if the current cache is valid 75 * 76 * @param[in] bus - The bus used for the service lookup 77 * @return True if the cache is valid false otherwise. 78 */ 79 bool isValid(sdbusplus::bus::bus& bus) const; 80 81 private: 82 /** @brief DBUS interface provided by the service */ 83 const std::string intf; 84 /** @brief DBUS path provided by the service */ 85 const std::string path; 86 /** @brief The name of the service if valid */ 87 std::optional<std::string> cachedService; 88 /** @brief The name of the bus used in the service lookup */ 89 std::optional<std::string> cachedBusName; 90 }; 91 92 /** 93 * @brief Get the DBUS Service name for the input dbus path 94 * 95 * @param[in] bus - DBUS Bus Object 96 * @param[in] intf - DBUS Interface 97 * @param[in] path - DBUS Object Path 98 * 99 */ 100 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf, 101 const std::string& path); 102 103 /** @brief Gets the dbus object info implementing the given interface 104 * from the given subtree. 105 * @param[in] bus - DBUS Bus Object. 106 * @param[in] interface - Dbus interface. 107 * @param[in] subtreePath - subtree from where the search should start. 108 * @param[in] match - identifier for object. 109 * @return On success returns the object having objectpath and servicename. 110 */ 111 DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus, 112 const std::string& interface, 113 const std::string& subtreePath = ROOT, 114 const std::string& match = {}); 115 116 /** @brief Get the ipObject of first dbus IP object of Non-LinkLocalIPAddress 117 * type from the given subtree, if not available gets IP object of 118 * LinkLocalIPAddress type. 119 * @param[in] bus - DBUS Bus Object. 120 * @param[in] interface - Dbus interface. 121 * @param[in] subtreePath - subtree from where the search should start. 122 * @param[in] match - identifier for object. 123 * @return On success returns the object having objectpath and servicename. 124 */ 125 DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus, 126 const std::string& interface, 127 const std::string& subtreePath, 128 const std::string& match); 129 130 /** @brief Gets the value associated with the given object 131 * and the interface. 132 * @param[in] bus - DBUS Bus Object. 133 * @param[in] service - Dbus service name. 134 * @param[in] objPath - Dbus object path. 135 * @param[in] interface - Dbus interface. 136 * @param[in] property - name of the property. 137 * @return On success returns the value of the property. 138 */ 139 Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service, 140 const std::string& objPath, const std::string& interface, 141 const std::string& property, 142 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 143 144 /** @brief Gets all the properties associated with the given object 145 * and the interface. 146 * @param[in] bus - DBUS Bus Object. 147 * @param[in] service - Dbus service name. 148 * @param[in] objPath - Dbus object path. 149 * @param[in] interface - Dbus interface. 150 * @return On success returns the map of name value pair. 151 */ 152 PropertyMap 153 getAllDbusProperties(sdbusplus::bus::bus& bus, const std::string& service, 154 const std::string& objPath, 155 const std::string& interface, 156 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 157 158 /** @brief Gets all managed objects associated with the given object 159 * path and service. 160 * @param[in] bus - D-Bus Bus Object. 161 * @param[in] service - D-Bus service name. 162 * @param[in] objPath - D-Bus object path. 163 * @return On success returns the map of name value pair. 164 */ 165 ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus, 166 const std::string& service, 167 const std::string& objPath); 168 169 /** @brief Sets the property value of the given object. 170 * @param[in] bus - DBUS Bus Object. 171 * @param[in] service - Dbus service name. 172 * @param[in] objPath - Dbus object path. 173 * @param[in] interface - Dbus interface. 174 * @param[in] property - name of the property. 175 * @param[in] value - value which needs to be set. 176 */ 177 void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service, 178 const std::string& objPath, const std::string& interface, 179 const std::string& property, const Value& value, 180 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 181 182 /** @brief Gets all the dbus objects from the given service root 183 * which matches the object identifier. 184 * @param[in] bus - DBUS Bus Object. 185 * @param[in] serviceRoot - Service root path. 186 * @param[in] interface - Dbus interface. 187 * @param[in] match - Identifier for a path. 188 * @returns map of object path and service info. 189 */ 190 ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus, 191 const std::string& serviceRoot, 192 const std::string& interface, 193 const std::string& match = {}); 194 195 /** @brief Deletes all the dbus objects from the given service root 196 which matches the object identifier. 197 * @param[in] bus - DBUS Bus Object. 198 * @param[in] serviceRoot - Service root path. 199 * @param[in] interface - Dbus interface. 200 * @param[in] match - Identifier for object. 201 */ 202 void deleteAllDbusObjects(sdbusplus::bus::bus& bus, 203 const std::string& serviceRoot, 204 const std::string& interface, 205 const std::string& match = {}); 206 207 /** @brief Gets the ancestor objects of the given object 208 which implements the given interface. 209 * @param[in] bus - Dbus bus object. 210 * @param[in] path - Child Dbus object path. 211 * @param[in] interfaces - Dbus interface list. 212 * @return map of object path and service info. 213 */ 214 ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path, 215 InterfaceList&& interfaces); 216 217 /** @struct VariantToDoubleVisitor 218 * @brief Visitor to convert variants to doubles 219 * @details Performs a static cast on the underlying type 220 */ 221 struct VariantToDoubleVisitor 222 { 223 template <typename T> 224 std::enable_if_t<std::is_arithmetic<T>::value, double> 225 operator()(const T& t) const 226 { 227 return static_cast<double>(t); 228 } 229 230 template <typename T> 231 std::enable_if_t<!std::is_arithmetic<T>::value, double> 232 operator()(const T& t) const 233 { 234 throw std::invalid_argument("Cannot translate type to double"); 235 } 236 }; 237 238 namespace method_no_args 239 { 240 241 /** @brief Calls the Dbus method which waits for response. 242 * @param[in] bus - DBUS Bus Object. 243 * @param[in] service - Dbus service name. 244 * @param[in] objPath - Dbus object path. 245 * @param[in] interface - Dbus interface. 246 * @param[in] method - Dbus method. 247 */ 248 void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service, 249 const std::string& objPath, const std::string& interface, 250 const std::string& method); 251 252 } // namespace method_no_args 253 254 namespace network 255 { 256 257 constexpr auto ROOT = "/xyz/openbmc_project/network"; 258 constexpr auto SERVICE = "xyz.openbmc_project.Network"; 259 constexpr auto IP_TYPE = "ipv4"; 260 constexpr auto IPV4_PREFIX = "169.254"; 261 constexpr auto IPV6_PREFIX = "fe80"; 262 constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP"; 263 constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress"; 264 constexpr auto SYSTEMCONFIG_INTERFACE = 265 "xyz.openbmc_project.Network.SystemConfiguration"; 266 constexpr auto ETHERNET_INTERFACE = 267 "xyz.openbmc_project.Network.EthernetInterface"; 268 constexpr auto IP_CREATE_INTERFACE = "xyz.openbmc_project.Network.IP.Create"; 269 constexpr auto VLAN_CREATE_INTERFACE = 270 "xyz.openbmc_project.Network.VLAN.Create"; 271 constexpr auto VLAN_INTERFACE = "xyz.openbmc_project.Network.VLAN"; 272 273 /* @brief converts the given subnet into prefix notation. 274 * @param[in] addressFamily - IP address family(AF_INET/AF_INET6). 275 * @param[in] mask - Subnet Mask. 276 * @returns prefix. 277 */ 278 uint8_t toPrefix(int addressFamily, const std::string& subnetMask); 279 280 /** @brief Sets the ip on the system. 281 * @param[in] bus - DBUS Bus Object. 282 * @param[in] service - Dbus service name. 283 * @param[in] objPath - Dbus object path. 284 * @param[in] protocolType - Protocol type 285 * @param[in] ipaddress - IPaddress. 286 * @param[in] prefix - Prefix length. 287 */ 288 void createIP(sdbusplus::bus::bus& bus, const std::string& service, 289 const std::string& objPath, const std::string& protocolType, 290 const std::string& ipaddress, uint8_t prefix); 291 292 /** @brief Creates the VLAN on the given interface. 293 * @param[in] bus - DBUS Bus Object. 294 * @param[in] service - Dbus service name. 295 * @param[in] objPath - Dbus object path. 296 * @param[in] interface - EthernetInterface. 297 * @param[in] vlanID - Vlan ID. 298 */ 299 void createVLAN(sdbusplus::bus::bus& bus, const std::string& service, 300 const std::string& objPath, const std::string& interface, 301 uint32_t vlanID); 302 303 /** @brief Gets the vlan id from the given object path. 304 * @param[in] path - Dbus object path. 305 */ 306 uint32_t getVLAN(const std::string& path); 307 308 } // namespace network 309 310 /** @brief Perform the low-level i2c bus write-read. 311 * @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2. 312 * @param[in] slaveAddr - i2c device slave address. 313 * @param[in] writeData - The data written to i2c device. 314 * @param[out] readBuf - Data read from the i2c device. 315 */ 316 ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr, 317 std::vector<uint8_t> writeData, 318 std::vector<uint8_t>& readBuf); 319 } // namespace ipmi 320