blob: 0cfaf01782c03f56320db354b9c271a292c1c7a9 [file] [log] [blame]
Patrick Venture690a2342020-05-17 11:51:31 -07001#pragma once
2
John Wang8a7236a2021-01-04 15:31:44 +08003#include "app/channel.hpp"
4#include "user_channel/cipher_mgmt.hpp"
5
6#include <arpa/inet.h>
7#include <netinet/ether.h>
8
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05009#include <ipmid/api-types.hpp>
10#include <ipmid/api.hpp>
11#include <ipmid/message.hpp>
12#include <ipmid/message/types.hpp>
13#include <ipmid/types.hpp>
14#include <ipmid/utils.hpp>
15#include <phosphor-logging/elog-errors.hpp>
16#include <phosphor-logging/elog.hpp>
17#include <phosphor-logging/log.hpp>
18#include <sdbusplus/bus.hpp>
19#include <sdbusplus/exception.hpp>
20#include <user_channel/channel_layer.hpp>
21#include <xyz/openbmc_project/Common/error.hpp>
22#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
23#include <xyz/openbmc_project/Network/IP/server.hpp>
24#include <xyz/openbmc_project/Network/Neighbor/server.hpp>
25
John Wang8a7236a2021-01-04 15:31:44 +080026#include <array>
27#include <bitset>
28#include <cinttypes>
Patrick Venture690a2342020-05-17 11:51:31 -070029#include <cstdint>
John Wang8a7236a2021-01-04 15:31:44 +080030#include <cstring>
31#include <fstream>
32#include <functional>
John Wang8a7236a2021-01-04 15:31:44 +080033#include <optional>
John Wang8a7236a2021-01-04 15:31:44 +080034#include <string>
35#include <string_view>
36#include <type_traits>
37#include <unordered_map>
38#include <unordered_set>
John Wang8a7236a2021-01-04 15:31:44 +080039#include <utility>
40#include <vector>
Patrick Venture690a2342020-05-17 11:51:31 -070041
42namespace ipmi
43{
44namespace transport
45{
46
John Wang8a7236a2021-01-04 15:31:44 +080047// D-Bus Network Daemon definitions
48constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
John Wang8a7236a2021-01-04 15:31:44 +080049constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
50constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
51constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";
52constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress";
53constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor";
54constexpr auto INTF_NEIGHBOR_CREATE_STATIC =
55 "xyz.openbmc_project.Network.Neighbor.CreateStatic";
56constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
57constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
58
Patrick Venture690a2342020-05-17 11:51:31 -070059/** @brief IPMI LAN Parameters */
60enum class LanParam : uint8_t
61{
62 SetStatus = 0,
63 AuthSupport = 1,
64 AuthEnables = 2,
65 IP = 3,
66 IPSrc = 4,
67 MAC = 5,
68 SubnetMask = 6,
69 Gateway1 = 12,
70 Gateway1MAC = 13,
71 VLANId = 20,
72 CiphersuiteSupport = 22,
73 CiphersuiteEntries = 23,
74 cipherSuitePrivilegeLevels = 24,
75 IPFamilySupport = 50,
76 IPFamilyEnables = 51,
77 IPv6Status = 55,
78 IPv6StaticAddresses = 56,
79 IPv6DynamicAddresses = 59,
80 IPv6RouterControl = 64,
81 IPv6StaticRouter1IP = 65,
82 IPv6StaticRouter1MAC = 66,
83 IPv6StaticRouter1PrefixLength = 67,
84 IPv6StaticRouter1PrefixValue = 68,
85};
86
87/** @brief IPMI IP Origin Types */
88enum class IPSrc : uint8_t
89{
90 Unspecified = 0,
91 Static = 1,
92 DHCP = 2,
93 BIOS = 3,
94 BMC = 4,
95};
96
97/** @brief IPMI Set Status */
98enum class SetStatus : uint8_t
99{
100 Complete = 0,
101 InProgress = 1,
102 Commit = 2,
103};
104
105/** @brief IPMI Family Suport Bits */
106namespace IPFamilySupportFlag
107{
108constexpr uint8_t IPv6Only = 0;
109constexpr uint8_t DualStack = 1;
110constexpr uint8_t IPv6Alerts = 2;
111} // namespace IPFamilySupportFlag
112
113/** @brief IPMI IPFamily Enables Flag */
114enum class IPFamilyEnables : uint8_t
115{
116 IPv4Only = 0,
117 IPv6Only = 1,
118 DualStack = 2,
119};
120
121/** @brief IPMI IPv6 Dyanmic Status Bits */
122namespace IPv6StatusFlag
123{
124constexpr uint8_t DHCP = 0;
125constexpr uint8_t SLAAC = 1;
126}; // namespace IPv6StatusFlag
127
128/** @brief IPMI IPv6 Source */
129enum class IPv6Source : uint8_t
130{
131 Static = 0,
132 SLAAC = 1,
133 DHCP = 2,
134};
135
136/** @brief IPMI IPv6 Address Status */
137enum class IPv6AddressStatus : uint8_t
138{
139 Active = 0,
140 Disabled = 1,
141};
142
143namespace IPv6RouterControlFlag
144{
145constexpr uint8_t Static = 0;
146constexpr uint8_t Dynamic = 1;
147}; // namespace IPv6RouterControlFlag
148
149// LAN Handler specific response codes
150constexpr Cc ccParamNotSupported = 0x80;
151constexpr Cc ccParamSetLocked = 0x81;
152constexpr Cc ccParamReadOnly = 0x82;
153
154// VLANs are a 12-bit value
155constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
156constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000;
157
158// Arbitrary v6 Address Limits to prevent too much output in ipmitool
159constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15;
160constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15;
161
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800162// Prefix length limits of phosphor-networkd
163constexpr uint8_t MIN_IPV4_PREFIX_LENGTH = 1;
164constexpr uint8_t MAX_IPV4_PREFIX_LENGTH = 32;
165constexpr uint8_t MIN_IPV6_PREFIX_LENGTH = 1;
166constexpr uint8_t MAX_IPV6_PREFIX_LENGTH = 128;
167
John Wang8a7236a2021-01-04 15:31:44 +0800168/** @brief The dbus parameters for the interface corresponding to a channel
169 * This helps reduce the number of mapper lookups we need for each
170 * query and simplifies finding the VLAN interface if needed.
171 */
172struct ChannelParams
173{
174 /** @brief The channel ID */
175 int id;
176 /** @brief channel name for the interface */
177 std::string ifname;
178 /** @brief Name of the service on the bus */
179 std::string service;
180 /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
181 std::string ifPath;
182 /** @brief Logical adapter path used for address assignment */
183 std::string logicalPath;
184};
185
186/** @brief A trivial helper used to determine if two PODs are equal
187 *
188 * @params[in] a - The first object to compare
189 * @params[in] b - The second object to compare
190 * @return True if the objects are the same bytewise
191 */
192template <typename T>
193bool equal(const T& a, const T& b)
194{
195 static_assert(std::is_trivially_copyable_v<T>);
196 return std::memcmp(&a, &b, sizeof(T)) == 0;
197}
198
199/** @brief Copies bytes from an array into a trivially copyable container
200 *
201 * @params[out] t - The container receiving the data
202 * @params[in] bytes - The data to copy
203 */
204template <size_t N, typename T>
205void copyInto(T& t, const std::array<uint8_t, N>& bytes)
206{
207 static_assert(std::is_trivially_copyable_v<T>);
208 static_assert(N == sizeof(T));
209 std::memcpy(&t, bytes.data(), bytes.size());
210}
211
212/** @brief Gets a generic view of the bytes in the input container
213 *
214 * @params[in] t - The data to reference
215 * @return A string_view referencing the bytes in the container
216 */
217template <typename T>
218std::string_view dataRef(const T& t)
219{
220 static_assert(std::is_trivially_copyable_v<T>);
221 return {reinterpret_cast<const char*>(&t), sizeof(T)};
222}
223
224/** @brief Determines the ethernet interface name corresponding to a channel
225 * Tries to map a VLAN object first so that the address information
226 * is accurate. Otherwise it gets the standard ethernet interface.
227 *
228 * @param[in] bus - The bus object used for lookups
229 * @param[in] channel - The channel id corresponding to an ethernet interface
230 * @return Ethernet interface service and object path if it exists
231 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500232std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
John Wang8a7236a2021-01-04 15:31:44 +0800233 uint8_t channel);
234
235/** @brief A trivial helper around maybeGetChannelParams() that throws an
236 * exception when it is unable to acquire parameters for the channel.
237 *
238 * @param[in] bus - The bus object used for lookups
239 * @param[in] channel - The channel id corresponding to an ethernet interface
240 * @return Ethernet interface service and object path
241 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500242ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel);
John Wang8a7236a2021-01-04 15:31:44 +0800243
244/** @brief Trivializes using parameter getter functions by providing a bus
245 * and channel parameters automatically.
246 *
247 * @param[in] channel - The channel id corresponding to an ethernet interface
248 * ...
249 */
250template <auto func, typename... Args>
251auto channelCall(uint8_t channel, Args&&... args)
252{
Patrick Williams5d82f472022-07-22 19:26:53 -0500253 sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
John Wang8a7236a2021-01-04 15:31:44 +0800254 auto params = getChannelParams(bus, channel);
255 return std::invoke(func, bus, params, std::forward<Args>(args)...);
256}
257
258/** @brief Generic paramters for different address families */
259template <int family>
260struct AddrFamily
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500261{};
John Wang8a7236a2021-01-04 15:31:44 +0800262
263/** @brief Parameter specialization for IPv4 */
264template <>
265struct AddrFamily<AF_INET>
266{
267 using addr = in_addr;
268 static constexpr auto protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700269 sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv4;
John Wang8a7236a2021-01-04 15:31:44 +0800270 static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
271 static constexpr uint8_t defaultPrefix = 32;
272 static constexpr char propertyGateway[] = "DefaultGateway";
273};
274
275/** @brief Parameter specialization for IPv6 */
276template <>
277struct AddrFamily<AF_INET6>
278{
279 using addr = in6_addr;
280 static constexpr auto protocol =
Willy Tu523e2d12023-09-05 11:36:48 -0700281 sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv6;
John Wang8a7236a2021-01-04 15:31:44 +0800282 static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
283 static constexpr uint8_t defaultPrefix = 128;
284 static constexpr char propertyGateway[] = "DefaultGateway6";
285};
286
287/** @brief Interface Neighbor configuration parameters */
288template <int family>
289struct IfNeigh
290{
291 std::string path;
292 typename AddrFamily<family>::addr ip;
293 ether_addr mac;
294};
295
296/** @brief Interface IP Address configuration parameters */
297template <int family>
298struct IfAddr
299{
300 std::string path;
301 typename AddrFamily<family>::addr address;
Willy Tu523e2d12023-09-05 11:36:48 -0700302 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin origin;
John Wang8a7236a2021-01-04 15:31:44 +0800303 uint8_t prefix;
304};
305
306/** @brief Valid address origins for IPv6 */
307static inline const std::unordered_set<
Willy Tu523e2d12023-09-05 11:36:48 -0700308 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
309 originsV6Static = {sdbusplus::server::xyz::openbmc_project::network::IP::
John Wang8a7236a2021-01-04 15:31:44 +0800310 AddressOrigin::Static};
311static inline const std::unordered_set<
Willy Tu523e2d12023-09-05 11:36:48 -0700312 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
John Wang8a7236a2021-01-04 15:31:44 +0800313 originsV6Dynamic = {
Willy Tu523e2d12023-09-05 11:36:48 -0700314 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
John Wang8a7236a2021-01-04 15:31:44 +0800315 DHCP,
Willy Tu523e2d12023-09-05 11:36:48 -0700316 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
John Wang8a7236a2021-01-04 15:31:44 +0800317 SLAAC,
318};
319
320/** @brief A lazy lookup mechanism for iterating over object properties stored
321 * in DBus. This will only perform the object lookup when needed, and
322 * retains a cache of previous lookups to speed up future iterations.
323 */
324class ObjectLookupCache
325{
326 public:
327 using PropertiesCache = std::unordered_map<std::string, PropertyMap>;
328
329 /** @brief Creates a new ObjectLookupCache for the interface on the bus
330 * NOTE: The inputs to this object must outlive the object since
331 * they are only referenced by it.
332 *
333 * @param[in] bus - The bus object used for lookups
334 * @param[in] params - The parameters for the channel
335 * @param[in] intf - The interface we are looking up
336 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500337 ObjectLookupCache(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800338 const char* intf) :
339 bus(bus),
340 params(params), intf(intf),
341 objs(getAllDbusObjects(bus, params.logicalPath, intf, ""))
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500342 {}
John Wang8a7236a2021-01-04 15:31:44 +0800343
344 class iterator : public ObjectTree::const_iterator
345 {
346 public:
347 using value_type = PropertiesCache::value_type;
348
349 iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
350 ObjectTree::const_iterator(it), container(container),
351 ret(container.cache.end())
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500352 {}
John Wang8a7236a2021-01-04 15:31:44 +0800353 value_type& operator*()
354 {
355 ret = container.get(ObjectTree::const_iterator::operator*().first);
356 return *ret;
357 }
358 value_type* operator->()
359 {
360 return &operator*();
361 }
362
363 private:
364 ObjectLookupCache& container;
365 PropertiesCache::iterator ret;
366 };
367
368 iterator begin() noexcept
369 {
370 return iterator(objs.begin(), *this);
371 }
372
373 iterator end() noexcept
374 {
375 return iterator(objs.end(), *this);
376 }
377
378 private:
Patrick Williams5d82f472022-07-22 19:26:53 -0500379 sdbusplus::bus_t& bus;
John Wang8a7236a2021-01-04 15:31:44 +0800380 const ChannelParams& params;
381 const char* const intf;
382 const ObjectTree objs;
383 PropertiesCache cache;
384
385 /** @brief Gets a cached copy of the object properties if possible
386 * Otherwise performs a query on DBus to look them up
387 *
388 * @param[in] path - The object path to lookup
389 * @return An iterator for the specified object path + properties
390 */
391 PropertiesCache::iterator get(const std::string& path)
392 {
393 auto it = cache.find(path);
394 if (it != cache.end())
395 {
396 return it;
397 }
398 auto properties = getAllDbusProperties(bus, params.service, path, intf);
399 return cache.insert({path, std::move(properties)}).first;
400 }
401};
402
403/** @brief Turns an IP address string into the network byte order form
404 * NOTE: This version strictly validates family matches
405 *
406 * @param[in] address - The string form of the address
407 * @return A network byte order address or none if conversion failed
408 */
409template <int family>
410std::optional<typename AddrFamily<family>::addr>
411 maybeStringToAddr(const char* address)
412{
413 typename AddrFamily<family>::addr ret;
414 if (inet_pton(family, address, &ret) == 1)
415 {
416 return ret;
417 }
418 return std::nullopt;
419}
420
421/** @brief Turns an IP address string into the network byte order form
422 * NOTE: This version strictly validates family matches
423 *
424 * @param[in] address - The string form of the address
425 * @return A network byte order address
426 */
427template <int family>
428typename AddrFamily<family>::addr stringToAddr(const char* address)
429{
430 auto ret = maybeStringToAddr<family>(address);
431 if (!ret)
432 {
433 phosphor::logging::log<phosphor::logging::level::ERR>(
434 "Failed to convert IP Address",
435 phosphor::logging::entry("FAMILY=%d", family),
436 phosphor::logging::entry("ADDRESS=%s", address));
437 phosphor::logging::elog<
Willy Tu523e2d12023-09-05 11:36:48 -0700438 sdbusplus::error::xyz::openbmc_project::common::InternalFailure>();
John Wang8a7236a2021-01-04 15:31:44 +0800439 }
440 return *ret;
441}
442
443/** @brief Turns an IP address in network byte order into a string
444 *
445 * @param[in] address - The string form of the address
446 * @return A network byte order address
447 */
448template <int family>
449std::string addrToString(const typename AddrFamily<family>::addr& address)
450{
451 std::string ret(AddrFamily<family>::maxStrLen, '\0');
452 inet_ntop(family, &address, ret.data(), ret.size());
453 ret.resize(strlen(ret.c_str()));
454 return ret;
455}
456
457/** @brief Converts a human readable MAC string into MAC bytes
458 *
459 * @param[in] mac - The MAC string
460 * @return MAC in bytes
461 */
462ether_addr stringToMAC(const char* mac);
463/** @brief Searches the ip object lookup cache for an address matching
464 * the input parameters. NOTE: The index lacks stability across address
465 * changes since the network daemon has no notion of stable indicies.
466 *
467 * @param[in] bus - The bus object used for lookups
468 * @param[in] params - The parameters for the channel
469 * @param[in] idx - The index of the desired address on the interface
470 * @param[in] origins - The allowed origins for the address objects
471 * @param[in] ips - The object lookup cache holding all of the address info
472 * @return The address and prefix if it was found
473 */
474template <int family>
475std::optional<IfAddr<family>> findIfAddr(
Patrick Williams5d82f472022-07-22 19:26:53 -0500476 [[maybe_unused]] sdbusplus::bus_t& bus,
Willy Tu11d68892022-01-20 10:37:34 -0800477 [[maybe_unused]] const ChannelParams& params, uint8_t idx,
John Wang8a7236a2021-01-04 15:31:44 +0800478 const std::unordered_set<
Willy Tu523e2d12023-09-05 11:36:48 -0700479 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
John Wang8a7236a2021-01-04 15:31:44 +0800480 origins,
481 ObjectLookupCache& ips)
482{
483 for (const auto& [path, properties] : ips)
484 {
485 const auto& addrStr = std::get<std::string>(properties.at("Address"));
486 auto addr = maybeStringToAddr<family>(addrStr.c_str());
487 if (!addr)
488 {
489 continue;
490 }
491
Willy Tu523e2d12023-09-05 11:36:48 -0700492 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin
493 origin = sdbusplus::server::xyz::openbmc_project::network::IP::
John Wang8a7236a2021-01-04 15:31:44 +0800494 convertAddressOriginFromString(
495 std::get<std::string>(properties.at("Origin")));
496 if (origins.find(origin) == origins.end())
497 {
498 continue;
499 }
500
501 if (idx > 0)
502 {
503 idx--;
504 continue;
505 }
506
507 IfAddr<family> ifaddr;
508 ifaddr.path = path;
509 ifaddr.address = *addr;
510 ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
511 ifaddr.origin = origin;
Willy Tu11d68892022-01-20 10:37:34 -0800512 return ifaddr;
John Wang8a7236a2021-01-04 15:31:44 +0800513 }
514
515 return std::nullopt;
516}
517/** @brief Trivial helper around findIfAddr that simplifies calls
518 * for one off lookups. Don't use this if you intend to do multiple
519 * lookups at a time.
520 *
521 * @param[in] bus - The bus object used for lookups
522 * @param[in] params - The parameters for the channel
523 * @param[in] idx - The index of the desired address on the interface
524 * @param[in] origins - The allowed origins for the address objects
525 * @return The address and prefix if it was found
526 */
527template <int family>
528auto getIfAddr(
Patrick Williams5d82f472022-07-22 19:26:53 -0500529 sdbusplus::bus_t& bus, const ChannelParams& params, uint8_t idx,
John Wang8a7236a2021-01-04 15:31:44 +0800530 const std::unordered_set<
Willy Tu523e2d12023-09-05 11:36:48 -0700531 sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
John Wang8a7236a2021-01-04 15:31:44 +0800532 origins)
533{
534 ObjectLookupCache ips(bus, params, INTF_IP);
535 return findIfAddr<family>(bus, params, idx, origins, ips);
536}
537
John Wang8a7236a2021-01-04 15:31:44 +0800538/** @brief Reconfigures the IPv6 address info configured for the interface
539 *
540 * @param[in] bus - The bus object used for lookups
541 * @param[in] params - The parameters for the channel
542 * @param[in] idx - The address index to operate on
543 * @param[in] address - The new address
544 * @param[in] prefix - The new address prefix
545 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500546void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800547 uint8_t idx, const in6_addr& address, uint8_t prefix);
548
549/** @brief Retrieves the current gateway for the address family on the system
Lei YUd1bd8c42021-08-11 17:13:56 +0800550 * NOTE: The gateway is per channel instead of the system wide one.
John Wang8a7236a2021-01-04 15:31:44 +0800551 *
552 * @param[in] bus - The bus object used for lookups
553 * @param[in] params - The parameters for the channel
554 * @return An address representing the gateway address if it exists
555 */
556template <int family>
557std::optional<typename AddrFamily<family>::addr>
Patrick Williams5d82f472022-07-22 19:26:53 -0500558 getGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
John Wang8a7236a2021-01-04 15:31:44 +0800559{
Lei YUd1bd8c42021-08-11 17:13:56 +0800560 auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
561 auto gatewayStr = std::get<std::string>(
562 getDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
563 AddrFamily<family>::propertyGateway));
John Wang8a7236a2021-01-04 15:31:44 +0800564 if (gatewayStr.empty())
565 {
566 return std::nullopt;
567 }
568 return stringToAddr<family>(gatewayStr.c_str());
569}
570
571template <int family>
572std::optional<IfNeigh<family>>
Patrick Williams5d82f472022-07-22 19:26:53 -0500573 findStaticNeighbor(sdbusplus::bus_t&, const ChannelParams&,
John Wang8a7236a2021-01-04 15:31:44 +0800574 const typename AddrFamily<family>::addr& ip,
575 ObjectLookupCache& neighbors)
576{
Willy Tu523e2d12023-09-05 11:36:48 -0700577 using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
John Wang8a7236a2021-01-04 15:31:44 +0800578 const auto state =
Willy Tu523e2d12023-09-05 11:36:48 -0700579 sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
John Wang8a7236a2021-01-04 15:31:44 +0800580 Neighbor::State::Permanent);
581 for (const auto& [path, neighbor] : neighbors)
582 {
583 const auto& ipStr = std::get<std::string>(neighbor.at("IPAddress"));
584 auto neighIP = maybeStringToAddr<family>(ipStr.c_str());
585 if (!neighIP)
586 {
587 continue;
588 }
589 if (!equal(*neighIP, ip))
590 {
591 continue;
592 }
593 if (state != std::get<std::string>(neighbor.at("State")))
594 {
595 continue;
596 }
597
598 IfNeigh<family> ret;
599 ret.path = path;
600 ret.ip = ip;
601 const auto& macStr = std::get<std::string>(neighbor.at("MACAddress"));
602 ret.mac = stringToMAC(macStr.c_str());
Willy Tu11d68892022-01-20 10:37:34 -0800603 return ret;
John Wang8a7236a2021-01-04 15:31:44 +0800604 }
605
606 return std::nullopt;
607}
608
609template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500610void createNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800611 const typename AddrFamily<family>::addr& address,
612 const ether_addr& mac)
613{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500614 auto newreq = bus.new_method_call(params.service.c_str(),
615 params.logicalPath.c_str(),
616 INTF_NEIGHBOR_CREATE_STATIC, "Neighbor");
John Wang8a7236a2021-01-04 15:31:44 +0800617 std::string macStr = ether_ntoa(&mac);
618 newreq.append(addrToString<family>(address), macStr);
619 bus.call_noreply(newreq);
620}
621
622/** @brief Deletes the dbus object. Ignores empty objects or objects that are
623 * missing from the bus.
624 *
625 * @param[in] bus - The bus object used for lookups
626 * @param[in] service - The name of the service
627 * @param[in] path - The path of the object to delete
628 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500629void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
John Wang8a7236a2021-01-04 15:31:44 +0800630 const std::string& path);
631
Lei YUd1bd8c42021-08-11 17:13:56 +0800632/** @brief Sets the value for the default gateway of the channel
John Wang8a7236a2021-01-04 15:31:44 +0800633 *
634 * @param[in] bus - The bus object used for lookups
635 * @param[in] params - The parameters for the channel
636 * @param[in] gateway - Gateway address to apply
637 */
638template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500639void setGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800640 const typename AddrFamily<family>::addr& address)
641{
642 // Save the old gateway MAC address if it exists so we can recreate it
643 auto gateway = getGatewayProperty<family>(bus, params);
644 std::optional<IfNeigh<family>> neighbor;
645 if (gateway)
646 {
647 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
648 neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors);
649 }
650
Lei YUd1bd8c42021-08-11 17:13:56 +0800651 auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
652 setDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
John Wang8a7236a2021-01-04 15:31:44 +0800653 AddrFamily<family>::propertyGateway,
654 addrToString<family>(address));
655
656 // Restore the gateway MAC if we had one
657 if (neighbor)
658 {
659 deleteObjectIfExists(bus, params.service, neighbor->path);
660 createNeighbor<family>(bus, params, address, neighbor->mac);
661 }
662}
663
Jian Zhang23f44652022-03-17 17:13:10 +0800664/** @enum SolConfParam
665 *
666 * using for Set/Get SOL configuration parameters command.
667 */
668enum class SolConfParam : uint8_t
669{
670 Progress, //!< Set In Progress.
671 Enable, //!< SOL Enable.
672 Authentication, //!< SOL Authentication.
673 Accumulate, //!< Character Accumulate Interval & Send Threshold.
674 Retry, //!< SOL Retry.
675 NonVbitrate, //!< SOL non-volatile bit rate.
676 Vbitrate, //!< SOL volatile bit rate.
677 Channel, //!< SOL payload channel.
678 Port, //!< SOL payload port.
679};
680
681constexpr uint8_t ipmiCCParamNotSupported = 0x80;
682constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
683
Patrick Venture690a2342020-05-17 11:51:31 -0700684} // namespace transport
685} // namespace ipmi