blob: 537ddc5961d2dc707bf4ac9236428f87a9b532e5 [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
9#include <array>
10#include <bitset>
11#include <cinttypes>
Patrick Venture690a2342020-05-17 11:51:31 -070012#include <cstdint>
John Wang8a7236a2021-01-04 15:31:44 +080013#include <cstring>
14#include <fstream>
15#include <functional>
Patrick Venture690a2342020-05-17 11:51:31 -070016#include <ipmid/api-types.hpp>
John Wang8a7236a2021-01-04 15:31:44 +080017#include <ipmid/api.hpp>
18#include <ipmid/message.hpp>
19#include <ipmid/message/types.hpp>
20#include <ipmid/types.hpp>
21#include <ipmid/utils.hpp>
22#include <optional>
23#include <phosphor-logging/elog-errors.hpp>
24#include <phosphor-logging/elog.hpp>
25#include <phosphor-logging/log.hpp>
26#include <sdbusplus/bus.hpp>
27#include <sdbusplus/exception.hpp>
28#include <string>
29#include <string_view>
30#include <type_traits>
31#include <unordered_map>
32#include <unordered_set>
33#include <user_channel/channel_layer.hpp>
34#include <utility>
35#include <vector>
36#include <xyz/openbmc_project/Common/error.hpp>
37#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
38#include <xyz/openbmc_project/Network/IP/server.hpp>
39#include <xyz/openbmc_project/Network/Neighbor/server.hpp>
Patrick Venture690a2342020-05-17 11:51:31 -070040
41namespace ipmi
42{
43namespace transport
44{
45
John Wang8a7236a2021-01-04 15:31:44 +080046// D-Bus Network Daemon definitions
47constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
John Wang8a7236a2021-01-04 15:31:44 +080048constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
49constexpr auto INTF_IP = "xyz.openbmc_project.Network.IP";
50constexpr auto INTF_IP_CREATE = "xyz.openbmc_project.Network.IP.Create";
51constexpr auto INTF_MAC = "xyz.openbmc_project.Network.MACAddress";
52constexpr auto INTF_NEIGHBOR = "xyz.openbmc_project.Network.Neighbor";
53constexpr auto INTF_NEIGHBOR_CREATE_STATIC =
54 "xyz.openbmc_project.Network.Neighbor.CreateStatic";
55constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
56constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
57
Patrick Venture690a2342020-05-17 11:51:31 -070058/** @brief IPMI LAN Parameters */
59enum class LanParam : uint8_t
60{
61 SetStatus = 0,
62 AuthSupport = 1,
63 AuthEnables = 2,
64 IP = 3,
65 IPSrc = 4,
66 MAC = 5,
67 SubnetMask = 6,
68 Gateway1 = 12,
69 Gateway1MAC = 13,
70 VLANId = 20,
71 CiphersuiteSupport = 22,
72 CiphersuiteEntries = 23,
73 cipherSuitePrivilegeLevels = 24,
74 IPFamilySupport = 50,
75 IPFamilyEnables = 51,
76 IPv6Status = 55,
77 IPv6StaticAddresses = 56,
78 IPv6DynamicAddresses = 59,
79 IPv6RouterControl = 64,
80 IPv6StaticRouter1IP = 65,
81 IPv6StaticRouter1MAC = 66,
82 IPv6StaticRouter1PrefixLength = 67,
83 IPv6StaticRouter1PrefixValue = 68,
84};
85
86/** @brief IPMI IP Origin Types */
87enum class IPSrc : uint8_t
88{
89 Unspecified = 0,
90 Static = 1,
91 DHCP = 2,
92 BIOS = 3,
93 BMC = 4,
94};
95
96/** @brief IPMI Set Status */
97enum class SetStatus : uint8_t
98{
99 Complete = 0,
100 InProgress = 1,
101 Commit = 2,
102};
103
104/** @brief IPMI Family Suport Bits */
105namespace IPFamilySupportFlag
106{
107constexpr uint8_t IPv6Only = 0;
108constexpr uint8_t DualStack = 1;
109constexpr uint8_t IPv6Alerts = 2;
110} // namespace IPFamilySupportFlag
111
112/** @brief IPMI IPFamily Enables Flag */
113enum class IPFamilyEnables : uint8_t
114{
115 IPv4Only = 0,
116 IPv6Only = 1,
117 DualStack = 2,
118};
119
120/** @brief IPMI IPv6 Dyanmic Status Bits */
121namespace IPv6StatusFlag
122{
123constexpr uint8_t DHCP = 0;
124constexpr uint8_t SLAAC = 1;
125}; // namespace IPv6StatusFlag
126
127/** @brief IPMI IPv6 Source */
128enum class IPv6Source : uint8_t
129{
130 Static = 0,
131 SLAAC = 1,
132 DHCP = 2,
133};
134
135/** @brief IPMI IPv6 Address Status */
136enum class IPv6AddressStatus : uint8_t
137{
138 Active = 0,
139 Disabled = 1,
140};
141
142namespace IPv6RouterControlFlag
143{
144constexpr uint8_t Static = 0;
145constexpr uint8_t Dynamic = 1;
146}; // namespace IPv6RouterControlFlag
147
148// LAN Handler specific response codes
149constexpr Cc ccParamNotSupported = 0x80;
150constexpr Cc ccParamSetLocked = 0x81;
151constexpr Cc ccParamReadOnly = 0x82;
152
153// VLANs are a 12-bit value
154constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
155constexpr uint16_t VLAN_ENABLE_FLAG = 0x8000;
156
157// Arbitrary v6 Address Limits to prevent too much output in ipmitool
158constexpr uint8_t MAX_IPV6_STATIC_ADDRESSES = 15;
159constexpr uint8_t MAX_IPV6_DYNAMIC_ADDRESSES = 15;
160
Jiaqing Zhao6d4a44e2022-01-24 15:04:00 +0800161// Prefix length limits of phosphor-networkd
162constexpr uint8_t MIN_IPV4_PREFIX_LENGTH = 1;
163constexpr uint8_t MAX_IPV4_PREFIX_LENGTH = 32;
164constexpr uint8_t MIN_IPV6_PREFIX_LENGTH = 1;
165constexpr uint8_t MAX_IPV6_PREFIX_LENGTH = 128;
166
John Wang8a7236a2021-01-04 15:31:44 +0800167/** @brief The dbus parameters for the interface corresponding to a channel
168 * This helps reduce the number of mapper lookups we need for each
169 * query and simplifies finding the VLAN interface if needed.
170 */
171struct ChannelParams
172{
173 /** @brief The channel ID */
174 int id;
175 /** @brief channel name for the interface */
176 std::string ifname;
177 /** @brief Name of the service on the bus */
178 std::string service;
179 /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
180 std::string ifPath;
181 /** @brief Logical adapter path used for address assignment */
182 std::string logicalPath;
183};
184
185/** @brief A trivial helper used to determine if two PODs are equal
186 *
187 * @params[in] a - The first object to compare
188 * @params[in] b - The second object to compare
189 * @return True if the objects are the same bytewise
190 */
191template <typename T>
192bool equal(const T& a, const T& b)
193{
194 static_assert(std::is_trivially_copyable_v<T>);
195 return std::memcmp(&a, &b, sizeof(T)) == 0;
196}
197
198/** @brief Copies bytes from an array into a trivially copyable container
199 *
200 * @params[out] t - The container receiving the data
201 * @params[in] bytes - The data to copy
202 */
203template <size_t N, typename T>
204void copyInto(T& t, const std::array<uint8_t, N>& bytes)
205{
206 static_assert(std::is_trivially_copyable_v<T>);
207 static_assert(N == sizeof(T));
208 std::memcpy(&t, bytes.data(), bytes.size());
209}
210
211/** @brief Gets a generic view of the bytes in the input container
212 *
213 * @params[in] t - The data to reference
214 * @return A string_view referencing the bytes in the container
215 */
216template <typename T>
217std::string_view dataRef(const T& t)
218{
219 static_assert(std::is_trivially_copyable_v<T>);
220 return {reinterpret_cast<const char*>(&t), sizeof(T)};
221}
222
223/** @brief Determines the ethernet interface name corresponding to a channel
224 * Tries to map a VLAN object first so that the address information
225 * is accurate. Otherwise it gets the standard ethernet interface.
226 *
227 * @param[in] bus - The bus object used for lookups
228 * @param[in] channel - The channel id corresponding to an ethernet interface
229 * @return Ethernet interface service and object path if it exists
230 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500231std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
John Wang8a7236a2021-01-04 15:31:44 +0800232 uint8_t channel);
233
234/** @brief A trivial helper around maybeGetChannelParams() that throws an
235 * exception when it is unable to acquire parameters for the channel.
236 *
237 * @param[in] bus - The bus object used for lookups
238 * @param[in] channel - The channel id corresponding to an ethernet interface
239 * @return Ethernet interface service and object path
240 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500241ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel);
John Wang8a7236a2021-01-04 15:31:44 +0800242
243/** @brief Trivializes using parameter getter functions by providing a bus
244 * and channel parameters automatically.
245 *
246 * @param[in] channel - The channel id corresponding to an ethernet interface
247 * ...
248 */
249template <auto func, typename... Args>
250auto channelCall(uint8_t channel, Args&&... args)
251{
Patrick Williams5d82f472022-07-22 19:26:53 -0500252 sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
John Wang8a7236a2021-01-04 15:31:44 +0800253 auto params = getChannelParams(bus, channel);
254 return std::invoke(func, bus, params, std::forward<Args>(args)...);
255}
256
257/** @brief Generic paramters for different address families */
258template <int family>
259struct AddrFamily
260{
261};
262
263/** @brief Parameter specialization for IPv4 */
264template <>
265struct AddrFamily<AF_INET>
266{
267 using addr = in_addr;
268 static constexpr auto protocol =
269 sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv4;
270 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 =
281 sdbusplus::xyz::openbmc_project::Network::server::IP::Protocol::IPv6;
282 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;
302 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin origin;
303 uint8_t prefix;
304};
305
306/** @brief Valid address origins for IPv6 */
307static inline const std::unordered_set<
308 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>
309 originsV6Static = {sdbusplus::xyz::openbmc_project::Network::server::IP::
310 AddressOrigin::Static};
311static inline const std::unordered_set<
312 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>
313 originsV6Dynamic = {
314 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin::
315 DHCP,
316 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin::
317 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, ""))
342 {
343 }
344
345 class iterator : public ObjectTree::const_iterator
346 {
347 public:
348 using value_type = PropertiesCache::value_type;
349
350 iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
351 ObjectTree::const_iterator(it), container(container),
352 ret(container.cache.end())
353 {
354 }
355 value_type& operator*()
356 {
357 ret = container.get(ObjectTree::const_iterator::operator*().first);
358 return *ret;
359 }
360 value_type* operator->()
361 {
362 return &operator*();
363 }
364
365 private:
366 ObjectLookupCache& container;
367 PropertiesCache::iterator ret;
368 };
369
370 iterator begin() noexcept
371 {
372 return iterator(objs.begin(), *this);
373 }
374
375 iterator end() noexcept
376 {
377 return iterator(objs.end(), *this);
378 }
379
380 private:
Patrick Williams5d82f472022-07-22 19:26:53 -0500381 sdbusplus::bus_t& bus;
John Wang8a7236a2021-01-04 15:31:44 +0800382 const ChannelParams& params;
383 const char* const intf;
384 const ObjectTree objs;
385 PropertiesCache cache;
386
387 /** @brief Gets a cached copy of the object properties if possible
388 * Otherwise performs a query on DBus to look them up
389 *
390 * @param[in] path - The object path to lookup
391 * @return An iterator for the specified object path + properties
392 */
393 PropertiesCache::iterator get(const std::string& path)
394 {
395 auto it = cache.find(path);
396 if (it != cache.end())
397 {
398 return it;
399 }
400 auto properties = getAllDbusProperties(bus, params.service, path, intf);
401 return cache.insert({path, std::move(properties)}).first;
402 }
403};
404
405/** @brief Turns an IP address string into the network byte order form
406 * NOTE: This version strictly validates family matches
407 *
408 * @param[in] address - The string form of the address
409 * @return A network byte order address or none if conversion failed
410 */
411template <int family>
412std::optional<typename AddrFamily<family>::addr>
413 maybeStringToAddr(const char* address)
414{
415 typename AddrFamily<family>::addr ret;
416 if (inet_pton(family, address, &ret) == 1)
417 {
418 return ret;
419 }
420 return std::nullopt;
421}
422
423/** @brief Turns an IP address string into the network byte order form
424 * NOTE: This version strictly validates family matches
425 *
426 * @param[in] address - The string form of the address
427 * @return A network byte order address
428 */
429template <int family>
430typename AddrFamily<family>::addr stringToAddr(const char* address)
431{
432 auto ret = maybeStringToAddr<family>(address);
433 if (!ret)
434 {
435 phosphor::logging::log<phosphor::logging::level::ERR>(
436 "Failed to convert IP Address",
437 phosphor::logging::entry("FAMILY=%d", family),
438 phosphor::logging::entry("ADDRESS=%s", address));
439 phosphor::logging::elog<
440 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
441 }
442 return *ret;
443}
444
445/** @brief Turns an IP address in network byte order into a string
446 *
447 * @param[in] address - The string form of the address
448 * @return A network byte order address
449 */
450template <int family>
451std::string addrToString(const typename AddrFamily<family>::addr& address)
452{
453 std::string ret(AddrFamily<family>::maxStrLen, '\0');
454 inet_ntop(family, &address, ret.data(), ret.size());
455 ret.resize(strlen(ret.c_str()));
456 return ret;
457}
458
459/** @brief Converts a human readable MAC string into MAC bytes
460 *
461 * @param[in] mac - The MAC string
462 * @return MAC in bytes
463 */
464ether_addr stringToMAC(const char* mac);
465/** @brief Searches the ip object lookup cache for an address matching
466 * the input parameters. NOTE: The index lacks stability across address
467 * changes since the network daemon has no notion of stable indicies.
468 *
469 * @param[in] bus - The bus object used for lookups
470 * @param[in] params - The parameters for the channel
471 * @param[in] idx - The index of the desired address on the interface
472 * @param[in] origins - The allowed origins for the address objects
473 * @param[in] ips - The object lookup cache holding all of the address info
474 * @return The address and prefix if it was found
475 */
476template <int family>
477std::optional<IfAddr<family>> findIfAddr(
Patrick Williams5d82f472022-07-22 19:26:53 -0500478 [[maybe_unused]] sdbusplus::bus_t& bus,
Willy Tu11d68892022-01-20 10:37:34 -0800479 [[maybe_unused]] const ChannelParams& params, uint8_t idx,
John Wang8a7236a2021-01-04 15:31:44 +0800480 const std::unordered_set<
481 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>&
482 origins,
483 ObjectLookupCache& ips)
484{
485 for (const auto& [path, properties] : ips)
486 {
487 const auto& addrStr = std::get<std::string>(properties.at("Address"));
488 auto addr = maybeStringToAddr<family>(addrStr.c_str());
489 if (!addr)
490 {
491 continue;
492 }
493
494 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin
495 origin = sdbusplus::xyz::openbmc_project::Network::server::IP::
496 convertAddressOriginFromString(
497 std::get<std::string>(properties.at("Origin")));
498 if (origins.find(origin) == origins.end())
499 {
500 continue;
501 }
502
503 if (idx > 0)
504 {
505 idx--;
506 continue;
507 }
508
509 IfAddr<family> ifaddr;
510 ifaddr.path = path;
511 ifaddr.address = *addr;
512 ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
513 ifaddr.origin = origin;
Willy Tu11d68892022-01-20 10:37:34 -0800514 return ifaddr;
John Wang8a7236a2021-01-04 15:31:44 +0800515 }
516
517 return std::nullopt;
518}
519/** @brief Trivial helper around findIfAddr that simplifies calls
520 * for one off lookups. Don't use this if you intend to do multiple
521 * lookups at a time.
522 *
523 * @param[in] bus - The bus object used for lookups
524 * @param[in] params - The parameters for the channel
525 * @param[in] idx - The index of the desired address on the interface
526 * @param[in] origins - The allowed origins for the address objects
527 * @return The address and prefix if it was found
528 */
529template <int family>
530auto getIfAddr(
Patrick Williams5d82f472022-07-22 19:26:53 -0500531 sdbusplus::bus_t& bus, const ChannelParams& params, uint8_t idx,
John Wang8a7236a2021-01-04 15:31:44 +0800532 const std::unordered_set<
533 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin>&
534 origins)
535{
536 ObjectLookupCache ips(bus, params, INTF_IP);
537 return findIfAddr<family>(bus, params, idx, origins, ips);
538}
539
540/** @brief Determines if the ethernet interface is using DHCP
541 *
542 * @param[in] bus - The bus object used for lookups
543 * @param[in] params - The parameters for the channel
544 * @return DHCPConf enumeration
545 */
546sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface::DHCPConf
Patrick Williams5d82f472022-07-22 19:26:53 -0500547 getDHCPProperty(sdbusplus::bus_t& bus, const ChannelParams& params);
John Wang8a7236a2021-01-04 15:31:44 +0800548
549/** @brief Sets the DHCP v6 state on the given interface
550 *
551 * @param[in] bus - The bus object used for lookups
552 * @param[in] params - The parameters for the channel
553 * @param[in] requestedDhcp - DHCP state to assign (none, v6, both)
554 * @param[in] defaultMode - True: Use algorithmic assignment
555 * False: requestedDhcp assigned unconditionally
556 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500557void setDHCPv6Property(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800558 const sdbusplus::xyz::openbmc_project::Network::server::
559 EthernetInterface::DHCPConf requestedDhcp,
560 const bool defaultMode);
561
562/** @brief Reconfigures the IPv6 address info configured for the interface
563 *
564 * @param[in] bus - The bus object used for lookups
565 * @param[in] params - The parameters for the channel
566 * @param[in] idx - The address index to operate on
567 * @param[in] address - The new address
568 * @param[in] prefix - The new address prefix
569 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500570void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800571 uint8_t idx, const in6_addr& address, uint8_t prefix);
572
573/** @brief Retrieves the current gateway for the address family on the system
Lei YUd1bd8c42021-08-11 17:13:56 +0800574 * NOTE: The gateway is per channel instead of the system wide one.
John Wang8a7236a2021-01-04 15:31:44 +0800575 *
576 * @param[in] bus - The bus object used for lookups
577 * @param[in] params - The parameters for the channel
578 * @return An address representing the gateway address if it exists
579 */
580template <int family>
581std::optional<typename AddrFamily<family>::addr>
Patrick Williams5d82f472022-07-22 19:26:53 -0500582 getGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
John Wang8a7236a2021-01-04 15:31:44 +0800583{
Lei YUd1bd8c42021-08-11 17:13:56 +0800584 auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
585 auto gatewayStr = std::get<std::string>(
586 getDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
587 AddrFamily<family>::propertyGateway));
John Wang8a7236a2021-01-04 15:31:44 +0800588 if (gatewayStr.empty())
589 {
590 return std::nullopt;
591 }
592 return stringToAddr<family>(gatewayStr.c_str());
593}
594
595template <int family>
596std::optional<IfNeigh<family>>
Patrick Williams5d82f472022-07-22 19:26:53 -0500597 findStaticNeighbor(sdbusplus::bus_t&, const ChannelParams&,
John Wang8a7236a2021-01-04 15:31:44 +0800598 const typename AddrFamily<family>::addr& ip,
599 ObjectLookupCache& neighbors)
600{
601 using sdbusplus::xyz::openbmc_project::Network::server::Neighbor;
602 const auto state =
603 sdbusplus::xyz::openbmc_project::Network::server::convertForMessage(
604 Neighbor::State::Permanent);
605 for (const auto& [path, neighbor] : neighbors)
606 {
607 const auto& ipStr = std::get<std::string>(neighbor.at("IPAddress"));
608 auto neighIP = maybeStringToAddr<family>(ipStr.c_str());
609 if (!neighIP)
610 {
611 continue;
612 }
613 if (!equal(*neighIP, ip))
614 {
615 continue;
616 }
617 if (state != std::get<std::string>(neighbor.at("State")))
618 {
619 continue;
620 }
621
622 IfNeigh<family> ret;
623 ret.path = path;
624 ret.ip = ip;
625 const auto& macStr = std::get<std::string>(neighbor.at("MACAddress"));
626 ret.mac = stringToMAC(macStr.c_str());
Willy Tu11d68892022-01-20 10:37:34 -0800627 return ret;
John Wang8a7236a2021-01-04 15:31:44 +0800628 }
629
630 return std::nullopt;
631}
632
633template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500634void createNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800635 const typename AddrFamily<family>::addr& address,
636 const ether_addr& mac)
637{
638 auto newreq =
639 bus.new_method_call(params.service.c_str(), params.logicalPath.c_str(),
640 INTF_NEIGHBOR_CREATE_STATIC, "Neighbor");
641 std::string macStr = ether_ntoa(&mac);
642 newreq.append(addrToString<family>(address), macStr);
643 bus.call_noreply(newreq);
644}
645
646/** @brief Deletes the dbus object. Ignores empty objects or objects that are
647 * missing from the bus.
648 *
649 * @param[in] bus - The bus object used for lookups
650 * @param[in] service - The name of the service
651 * @param[in] path - The path of the object to delete
652 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500653void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
John Wang8a7236a2021-01-04 15:31:44 +0800654 const std::string& path);
655
Lei YUd1bd8c42021-08-11 17:13:56 +0800656/** @brief Sets the value for the default gateway of the channel
John Wang8a7236a2021-01-04 15:31:44 +0800657 *
658 * @param[in] bus - The bus object used for lookups
659 * @param[in] params - The parameters for the channel
660 * @param[in] gateway - Gateway address to apply
661 */
662template <int family>
Patrick Williams5d82f472022-07-22 19:26:53 -0500663void setGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
John Wang8a7236a2021-01-04 15:31:44 +0800664 const typename AddrFamily<family>::addr& address)
665{
666 // Save the old gateway MAC address if it exists so we can recreate it
667 auto gateway = getGatewayProperty<family>(bus, params);
668 std::optional<IfNeigh<family>> neighbor;
669 if (gateway)
670 {
671 ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
672 neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors);
673 }
674
Lei YUd1bd8c42021-08-11 17:13:56 +0800675 auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
676 setDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
John Wang8a7236a2021-01-04 15:31:44 +0800677 AddrFamily<family>::propertyGateway,
678 addrToString<family>(address));
679
680 // Restore the gateway MAC if we had one
681 if (neighbor)
682 {
683 deleteObjectIfExists(bus, params.service, neighbor->path);
684 createNeighbor<family>(bus, params, address, neighbor->mac);
685 }
686}
687
Jian Zhang23f44652022-03-17 17:13:10 +0800688/** @enum SolConfParam
689 *
690 * using for Set/Get SOL configuration parameters command.
691 */
692enum class SolConfParam : uint8_t
693{
694 Progress, //!< Set In Progress.
695 Enable, //!< SOL Enable.
696 Authentication, //!< SOL Authentication.
697 Accumulate, //!< Character Accumulate Interval & Send Threshold.
698 Retry, //!< SOL Retry.
699 NonVbitrate, //!< SOL non-volatile bit rate.
700 Vbitrate, //!< SOL volatile bit rate.
701 Channel, //!< SOL payload channel.
702 Port, //!< SOL payload port.
703};
704
705constexpr uint8_t ipmiCCParamNotSupported = 0x80;
706constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
707
Patrick Venture690a2342020-05-17 11:51:31 -0700708} // namespace transport
709} // namespace ipmi