1690a2342SPatrick Venture #pragma once
2690a2342SPatrick Venture 
38a7236aeSJohn Wang #include "app/channel.hpp"
4*0893ca3cSPeter Foley #include "transportconstants.hpp"
58a7236aeSJohn Wang #include "user_channel/cipher_mgmt.hpp"
68a7236aeSJohn Wang 
7fbc6c9d7SPatrick Williams #include <ipmid/api-types.hpp>
8fbc6c9d7SPatrick Williams #include <ipmid/api.hpp>
9fbc6c9d7SPatrick Williams #include <ipmid/message.hpp>
10fbc6c9d7SPatrick Williams #include <ipmid/message/types.hpp>
11fbc6c9d7SPatrick Williams #include <ipmid/types.hpp>
12fbc6c9d7SPatrick Williams #include <ipmid/utils.hpp>
13fbc6c9d7SPatrick Williams #include <phosphor-logging/elog-errors.hpp>
14fbc6c9d7SPatrick Williams #include <phosphor-logging/elog.hpp>
15fbc6c9d7SPatrick Williams #include <phosphor-logging/log.hpp>
16fbc6c9d7SPatrick Williams #include <sdbusplus/bus.hpp>
17fbc6c9d7SPatrick Williams #include <sdbusplus/exception.hpp>
18726f2bddSWilliam A. Kennington III #include <stdplus/net/addr/ether.hpp>
19726f2bddSWilliam A. Kennington III #include <stdplus/net/addr/ip.hpp>
20726f2bddSWilliam A. Kennington III #include <stdplus/str/conv.hpp>
21c72f3602SWilliam A. Kennington III #include <stdplus/zstring_view.hpp>
22fbc6c9d7SPatrick Williams #include <user_channel/channel_layer.hpp>
23fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
24fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
25fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/IP/server.hpp>
26fbc6c9d7SPatrick Williams #include <xyz/openbmc_project/Network/Neighbor/server.hpp>
27fbc6c9d7SPatrick Williams 
288a7236aeSJohn Wang #include <cinttypes>
298a7236aeSJohn Wang #include <functional>
308a7236aeSJohn Wang #include <optional>
318a7236aeSJohn Wang #include <string>
328a7236aeSJohn Wang #include <string_view>
338a7236aeSJohn Wang #include <unordered_map>
348a7236aeSJohn Wang #include <unordered_set>
358a7236aeSJohn Wang #include <utility>
36690a2342SPatrick Venture 
37690a2342SPatrick Venture namespace ipmi
38690a2342SPatrick Venture {
39690a2342SPatrick Venture namespace transport
40690a2342SPatrick Venture {
41690a2342SPatrick Venture 
428a7236aeSJohn Wang /** @brief The dbus parameters for the interface corresponding to a channel
438a7236aeSJohn Wang  *         This helps reduce the number of mapper lookups we need for each
448a7236aeSJohn Wang  *         query and simplifies finding the VLAN interface if needed.
458a7236aeSJohn Wang  */
468a7236aeSJohn Wang struct ChannelParams
478a7236aeSJohn Wang {
488a7236aeSJohn Wang     /** @brief The channel ID */
498a7236aeSJohn Wang     int id;
508a7236aeSJohn Wang     /** @brief channel name for the interface */
518a7236aeSJohn Wang     std::string ifname;
528a7236aeSJohn Wang     /** @brief Name of the service on the bus */
538a7236aeSJohn Wang     std::string service;
548a7236aeSJohn Wang     /** @brief Lower level adapter path that is guaranteed to not be a VLAN */
558a7236aeSJohn Wang     std::string ifPath;
568a7236aeSJohn Wang     /** @brief Logical adapter path used for address assignment */
578a7236aeSJohn Wang     std::string logicalPath;
588a7236aeSJohn Wang };
598a7236aeSJohn Wang 
608a7236aeSJohn Wang /** @brief Determines the ethernet interface name corresponding to a channel
618a7236aeSJohn Wang  *         Tries to map a VLAN object first so that the address information
628a7236aeSJohn Wang  *         is accurate. Otherwise it gets the standard ethernet interface.
638a7236aeSJohn Wang  *
648a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
658a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
668a7236aeSJohn Wang  *  @return Ethernet interface service and object path if it exists
678a7236aeSJohn Wang  */
685d82f474SPatrick Williams std::optional<ChannelParams> maybeGetChannelParams(sdbusplus::bus_t& bus,
698a7236aeSJohn Wang                                                    uint8_t channel);
708a7236aeSJohn Wang 
718a7236aeSJohn Wang /** @brief A trivial helper around maybeGetChannelParams() that throws an
728a7236aeSJohn Wang  *         exception when it is unable to acquire parameters for the channel.
738a7236aeSJohn Wang  *
748a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
758a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
768a7236aeSJohn Wang  *  @return Ethernet interface service and object path
778a7236aeSJohn Wang  */
785d82f474SPatrick Williams ChannelParams getChannelParams(sdbusplus::bus_t& bus, uint8_t channel);
798a7236aeSJohn Wang 
808a7236aeSJohn Wang /** @brief Trivializes using parameter getter functions by providing a bus
818a7236aeSJohn Wang  *         and channel parameters automatically.
828a7236aeSJohn Wang  *
838a7236aeSJohn Wang  *  @param[in] channel - The channel id corresponding to an ethernet interface
848a7236aeSJohn Wang  *  ...
858a7236aeSJohn Wang  */
868a7236aeSJohn Wang template <auto func, typename... Args>
channelCall(uint8_t channel,Args &&...args)878a7236aeSJohn Wang auto channelCall(uint8_t channel, Args&&... args)
888a7236aeSJohn Wang {
895d82f474SPatrick Williams     sdbusplus::bus_t bus(ipmid_get_sd_bus_connection());
908a7236aeSJohn Wang     auto params = getChannelParams(bus, channel);
918a7236aeSJohn Wang     return std::invoke(func, bus, params, std::forward<Args>(args)...);
928a7236aeSJohn Wang }
938a7236aeSJohn Wang 
948a7236aeSJohn Wang /** @brief Generic paramters for different address families */
958a7236aeSJohn Wang template <int family>
968a7236aeSJohn Wang struct AddrFamily
97fbc6c9d7SPatrick Williams {};
988a7236aeSJohn Wang 
998a7236aeSJohn Wang /** @brief Parameter specialization for IPv4 */
1008a7236aeSJohn Wang template <>
1018a7236aeSJohn Wang struct AddrFamily<AF_INET>
1028a7236aeSJohn Wang {
103726f2bddSWilliam A. Kennington III     using addr = stdplus::In4Addr;
1048a7236aeSJohn Wang     static constexpr auto protocol =
105523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv4;
1068a7236aeSJohn Wang     static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
1078a7236aeSJohn Wang     static constexpr uint8_t defaultPrefix = 32;
1088a7236aeSJohn Wang     static constexpr char propertyGateway[] = "DefaultGateway";
1098a7236aeSJohn Wang };
1108a7236aeSJohn Wang 
1118a7236aeSJohn Wang /** @brief Parameter specialization for IPv6 */
1128a7236aeSJohn Wang template <>
1138a7236aeSJohn Wang struct AddrFamily<AF_INET6>
1148a7236aeSJohn Wang {
115726f2bddSWilliam A. Kennington III     using addr = stdplus::In6Addr;
1168a7236aeSJohn Wang     static constexpr auto protocol =
117523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::Protocol::IPv6;
1188a7236aeSJohn Wang     static constexpr size_t maxStrLen = INET6_ADDRSTRLEN;
1198a7236aeSJohn Wang     static constexpr uint8_t defaultPrefix = 128;
1208a7236aeSJohn Wang     static constexpr char propertyGateway[] = "DefaultGateway6";
1218a7236aeSJohn Wang };
1228a7236aeSJohn Wang 
1238a7236aeSJohn Wang /** @brief Interface Neighbor configuration parameters */
1248a7236aeSJohn Wang template <int family>
1258a7236aeSJohn Wang struct IfNeigh
1268a7236aeSJohn Wang {
1278a7236aeSJohn Wang     std::string path;
1288a7236aeSJohn Wang     typename AddrFamily<family>::addr ip;
129726f2bddSWilliam A. Kennington III     stdplus::EtherAddr mac;
1308a7236aeSJohn Wang };
1318a7236aeSJohn Wang 
1328a7236aeSJohn Wang /** @brief Interface IP Address configuration parameters */
1338a7236aeSJohn Wang template <int family>
1348a7236aeSJohn Wang struct IfAddr
1358a7236aeSJohn Wang {
1368a7236aeSJohn Wang     std::string path;
1378a7236aeSJohn Wang     typename AddrFamily<family>::addr address;
138523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin origin;
1398a7236aeSJohn Wang     uint8_t prefix;
1408a7236aeSJohn Wang };
1418a7236aeSJohn Wang 
1428a7236aeSJohn Wang /** @brief Valid address origins for IPv6 */
1438a7236aeSJohn Wang static inline const std::unordered_set<
144523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
145523e2d1bSWilly Tu     originsV6Static = {sdbusplus::server::xyz::openbmc_project::network::IP::
1468a7236aeSJohn Wang                            AddressOrigin::Static};
1478a7236aeSJohn Wang static inline const std::unordered_set<
148523e2d1bSWilly Tu     sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>
1498a7236aeSJohn Wang     originsV6Dynamic = {
150523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
1518a7236aeSJohn Wang             DHCP,
152523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin::
1538a7236aeSJohn Wang             SLAAC,
1548a7236aeSJohn Wang };
1558a7236aeSJohn Wang 
1568a7236aeSJohn Wang /** @brief A lazy lookup mechanism for iterating over object properties stored
1578a7236aeSJohn Wang  *         in DBus. This will only perform the object lookup when needed, and
1588a7236aeSJohn Wang  *         retains a cache of previous lookups to speed up future iterations.
1598a7236aeSJohn Wang  */
1608a7236aeSJohn Wang class ObjectLookupCache
1618a7236aeSJohn Wang {
1628a7236aeSJohn Wang   public:
1638a7236aeSJohn Wang     using PropertiesCache = std::unordered_map<std::string, PropertyMap>;
1648a7236aeSJohn Wang 
1658a7236aeSJohn Wang     /** @brief Creates a new ObjectLookupCache for the interface on the bus
1668a7236aeSJohn Wang      *         NOTE: The inputs to this object must outlive the object since
1678a7236aeSJohn Wang      *         they are only referenced by it.
1688a7236aeSJohn Wang      *
1698a7236aeSJohn Wang      *  @param[in] bus    - The bus object used for lookups
1708a7236aeSJohn Wang      *  @param[in] params - The parameters for the channel
1718a7236aeSJohn Wang      *  @param[in] intf   - The interface we are looking up
1728a7236aeSJohn Wang      */
ObjectLookupCache(sdbusplus::bus_t & bus,const ChannelParams & params,const char * intf)1735d82f474SPatrick Williams     ObjectLookupCache(sdbusplus::bus_t& bus, const ChannelParams& params,
1748a7236aeSJohn Wang                       const char* intf) :
1758a7236aeSJohn Wang         bus(bus),
1768a7236aeSJohn Wang         params(params), intf(intf),
1778a7236aeSJohn Wang         objs(getAllDbusObjects(bus, params.logicalPath, intf, ""))
178fbc6c9d7SPatrick Williams     {}
1798a7236aeSJohn Wang 
1808a7236aeSJohn Wang     class iterator : public ObjectTree::const_iterator
1818a7236aeSJohn Wang     {
1828a7236aeSJohn Wang       public:
1838a7236aeSJohn Wang         using value_type = PropertiesCache::value_type;
1848a7236aeSJohn Wang 
iterator(ObjectTree::const_iterator it,ObjectLookupCache & container)1858a7236aeSJohn Wang         iterator(ObjectTree::const_iterator it, ObjectLookupCache& container) :
1868a7236aeSJohn Wang             ObjectTree::const_iterator(it), container(container),
1878a7236aeSJohn Wang             ret(container.cache.end())
188fbc6c9d7SPatrick Williams         {}
operator *()1898a7236aeSJohn Wang         value_type& operator*()
1908a7236aeSJohn Wang         {
1918a7236aeSJohn Wang             ret = container.get(ObjectTree::const_iterator::operator*().first);
1928a7236aeSJohn Wang             return *ret;
1938a7236aeSJohn Wang         }
operator ->()1948a7236aeSJohn Wang         value_type* operator->()
1958a7236aeSJohn Wang         {
1968a7236aeSJohn Wang             return &operator*();
1978a7236aeSJohn Wang         }
1988a7236aeSJohn Wang 
1998a7236aeSJohn Wang       private:
2008a7236aeSJohn Wang         ObjectLookupCache& container;
2018a7236aeSJohn Wang         PropertiesCache::iterator ret;
2028a7236aeSJohn Wang     };
2038a7236aeSJohn Wang 
begin()2048a7236aeSJohn Wang     iterator begin() noexcept
2058a7236aeSJohn Wang     {
2068a7236aeSJohn Wang         return iterator(objs.begin(), *this);
2078a7236aeSJohn Wang     }
2088a7236aeSJohn Wang 
end()2098a7236aeSJohn Wang     iterator end() noexcept
2108a7236aeSJohn Wang     {
2118a7236aeSJohn Wang         return iterator(objs.end(), *this);
2128a7236aeSJohn Wang     }
2138a7236aeSJohn Wang 
2148a7236aeSJohn Wang   private:
2155d82f474SPatrick Williams     sdbusplus::bus_t& bus;
2168a7236aeSJohn Wang     const ChannelParams& params;
2178a7236aeSJohn Wang     const char* const intf;
2188a7236aeSJohn Wang     const ObjectTree objs;
2198a7236aeSJohn Wang     PropertiesCache cache;
2208a7236aeSJohn Wang 
2218a7236aeSJohn Wang     /** @brief Gets a cached copy of the object properties if possible
2228a7236aeSJohn Wang      *         Otherwise performs a query on DBus to look them up
2238a7236aeSJohn Wang      *
2248a7236aeSJohn Wang      *  @param[in] path - The object path to lookup
2258a7236aeSJohn Wang      *  @return An iterator for the specified object path + properties
2268a7236aeSJohn Wang      */
get(const std::string & path)2278a7236aeSJohn Wang     PropertiesCache::iterator get(const std::string& path)
2288a7236aeSJohn Wang     {
2298a7236aeSJohn Wang         auto it = cache.find(path);
2308a7236aeSJohn Wang         if (it != cache.end())
2318a7236aeSJohn Wang         {
2328a7236aeSJohn Wang             return it;
2338a7236aeSJohn Wang         }
2348a7236aeSJohn Wang         auto properties = getAllDbusProperties(bus, params.service, path, intf);
2358a7236aeSJohn Wang         return cache.insert({path, std::move(properties)}).first;
2368a7236aeSJohn Wang     }
2378a7236aeSJohn Wang };
2388a7236aeSJohn Wang 
2398a7236aeSJohn Wang /** @brief Searches the ip object lookup cache for an address matching
2408a7236aeSJohn Wang  *         the input parameters. NOTE: The index lacks stability across address
2418a7236aeSJohn Wang  *         changes since the network daemon has no notion of stable indicies.
2428a7236aeSJohn Wang  *
2438a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
2448a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
2458a7236aeSJohn Wang  *  @param[in] idx     - The index of the desired address on the interface
2468a7236aeSJohn Wang  *  @param[in] origins - The allowed origins for the address objects
2478a7236aeSJohn Wang  *  @param[in] ips     - The object lookup cache holding all of the address info
2488a7236aeSJohn Wang  *  @return The address and prefix if it was found
2498a7236aeSJohn Wang  */
2508a7236aeSJohn Wang template <int family>
findIfAddr(sdbusplus::bus_t & bus,const ChannelParams & params,uint8_t idx,const std::unordered_set<sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin> & origins,ObjectLookupCache & ips)2518a7236aeSJohn Wang std::optional<IfAddr<family>> findIfAddr(
2525d82f474SPatrick Williams     [[maybe_unused]] sdbusplus::bus_t& bus,
25311d68897SWilly Tu     [[maybe_unused]] const ChannelParams& params, uint8_t idx,
2548a7236aeSJohn Wang     const std::unordered_set<
255523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
2568a7236aeSJohn Wang         origins,
2578a7236aeSJohn Wang     ObjectLookupCache& ips)
2588a7236aeSJohn Wang {
2598a7236aeSJohn Wang     for (const auto& [path, properties] : ips)
2608a7236aeSJohn Wang     {
261726f2bddSWilliam A. Kennington III         std::optional<typename AddrFamily<family>::addr> addr;
262726f2bddSWilliam A. Kennington III         try
263726f2bddSWilliam A. Kennington III         {
264726f2bddSWilliam A. Kennington III             addr.emplace(stdplus::fromStr<typename AddrFamily<family>::addr>(
265726f2bddSWilliam A. Kennington III                 std::get<std::string>(properties.at("Address"))));
266726f2bddSWilliam A. Kennington III         }
267726f2bddSWilliam A. Kennington III         catch (...)
2688a7236aeSJohn Wang         {
2698a7236aeSJohn Wang             continue;
2708a7236aeSJohn Wang         }
2718a7236aeSJohn Wang 
272523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin
273523e2d1bSWilly Tu             origin = sdbusplus::server::xyz::openbmc_project::network::IP::
2748a7236aeSJohn Wang                 convertAddressOriginFromString(
2758a7236aeSJohn Wang                     std::get<std::string>(properties.at("Origin")));
2768a7236aeSJohn Wang         if (origins.find(origin) == origins.end())
2778a7236aeSJohn Wang         {
2788a7236aeSJohn Wang             continue;
2798a7236aeSJohn Wang         }
2808a7236aeSJohn Wang 
2818a7236aeSJohn Wang         if (idx > 0)
2828a7236aeSJohn Wang         {
2838a7236aeSJohn Wang             idx--;
2848a7236aeSJohn Wang             continue;
2858a7236aeSJohn Wang         }
2868a7236aeSJohn Wang 
2878a7236aeSJohn Wang         IfAddr<family> ifaddr;
2888a7236aeSJohn Wang         ifaddr.path = path;
2898a7236aeSJohn Wang         ifaddr.address = *addr;
2908a7236aeSJohn Wang         ifaddr.prefix = std::get<uint8_t>(properties.at("PrefixLength"));
2918a7236aeSJohn Wang         ifaddr.origin = origin;
29211d68897SWilly Tu         return ifaddr;
2938a7236aeSJohn Wang     }
2948a7236aeSJohn Wang 
2958a7236aeSJohn Wang     return std::nullopt;
2968a7236aeSJohn Wang }
2978a7236aeSJohn Wang /** @brief Trivial helper around findIfAddr that simplifies calls
2988a7236aeSJohn Wang  *         for one off lookups. Don't use this if you intend to do multiple
2998a7236aeSJohn Wang  *         lookups at a time.
3008a7236aeSJohn Wang  *
3018a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
3028a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
3038a7236aeSJohn Wang  *  @param[in] idx     - The index of the desired address on the interface
3048a7236aeSJohn Wang  *  @param[in] origins - The allowed origins for the address objects
3058a7236aeSJohn Wang  *  @return The address and prefix if it was found
3068a7236aeSJohn Wang  */
3078a7236aeSJohn Wang template <int family>
getIfAddr(sdbusplus::bus_t & bus,const ChannelParams & params,uint8_t idx,const std::unordered_set<sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin> & origins)3088a7236aeSJohn Wang auto getIfAddr(
3095d82f474SPatrick Williams     sdbusplus::bus_t& bus, const ChannelParams& params, uint8_t idx,
3108a7236aeSJohn Wang     const std::unordered_set<
311523e2d1bSWilly Tu         sdbusplus::server::xyz::openbmc_project::network::IP::AddressOrigin>&
3128a7236aeSJohn Wang         origins)
3138a7236aeSJohn Wang {
3148a7236aeSJohn Wang     ObjectLookupCache ips(bus, params, INTF_IP);
3158a7236aeSJohn Wang     return findIfAddr<family>(bus, params, idx, origins, ips);
3168a7236aeSJohn Wang }
3178a7236aeSJohn Wang 
3188a7236aeSJohn Wang /** @brief Reconfigures the IPv6 address info configured for the interface
3198a7236aeSJohn Wang  *
3208a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
3218a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
3228a7236aeSJohn Wang  *  @param[in] idx     - The address index to operate on
3238a7236aeSJohn Wang  *  @param[in] address - The new address
3248a7236aeSJohn Wang  *  @param[in] prefix  - The new address prefix
3258a7236aeSJohn Wang  */
3265d82f474SPatrick Williams void reconfigureIfAddr6(sdbusplus::bus_t& bus, const ChannelParams& params,
327726f2bddSWilliam A. Kennington III                         uint8_t idx, stdplus::In6Addr address, uint8_t prefix);
3288a7236aeSJohn Wang 
3298a7236aeSJohn Wang /** @brief Retrieves the current gateway for the address family on the system
330d1bd8c48SLei YU  *         NOTE: The gateway is per channel instead of the system wide one.
3318a7236aeSJohn Wang  *
3328a7236aeSJohn Wang  *  @param[in] bus    - The bus object used for lookups
3338a7236aeSJohn Wang  *  @param[in] params - The parameters for the channel
3348a7236aeSJohn Wang  *  @return An address representing the gateway address if it exists
3358a7236aeSJohn Wang  */
3368a7236aeSJohn Wang template <int family>
3378a7236aeSJohn Wang std::optional<typename AddrFamily<family>::addr>
getGatewayProperty(sdbusplus::bus_t & bus,const ChannelParams & params)3385d82f474SPatrick Williams     getGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params)
3398a7236aeSJohn Wang {
340d1bd8c48SLei YU     auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
341d1bd8c48SLei YU     auto gatewayStr = std::get<std::string>(
342d1bd8c48SLei YU         getDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
3438a7236aeSJohn Wang                         AddrFamily<family>::propertyGateway));
3448a7236aeSJohn Wang     if (gatewayStr.empty())
3458a7236aeSJohn Wang     {
3468a7236aeSJohn Wang         return std::nullopt;
3478a7236aeSJohn Wang     }
348726f2bddSWilliam A. Kennington III     return stdplus::fromStr<typename AddrFamily<family>::addr>(gatewayStr);
3498a7236aeSJohn Wang }
3508a7236aeSJohn Wang 
3518a7236aeSJohn Wang template <int family>
3528a7236aeSJohn Wang std::optional<IfNeigh<family>>
findStaticNeighbor(sdbusplus::bus_t &,const ChannelParams &,typename AddrFamily<family>::addr ip,ObjectLookupCache & neighbors)3535d82f474SPatrick Williams     findStaticNeighbor(sdbusplus::bus_t&, const ChannelParams&,
354726f2bddSWilliam A. Kennington III                        typename AddrFamily<family>::addr ip,
3558a7236aeSJohn Wang                        ObjectLookupCache& neighbors)
3568a7236aeSJohn Wang {
357523e2d1bSWilly Tu     using sdbusplus::server::xyz::openbmc_project::network::Neighbor;
3588a7236aeSJohn Wang     const auto state =
359523e2d1bSWilly Tu         sdbusplus::common::xyz::openbmc_project::network::convertForMessage(
3608a7236aeSJohn Wang             Neighbor::State::Permanent);
3618a7236aeSJohn Wang     for (const auto& [path, neighbor] : neighbors)
3628a7236aeSJohn Wang     {
363726f2bddSWilliam A. Kennington III         std::optional<typename AddrFamily<family>::addr> neighIP;
364726f2bddSWilliam A. Kennington III         try
365726f2bddSWilliam A. Kennington III         {
366726f2bddSWilliam A. Kennington III             neighIP.emplace(stdplus::fromStr<typename AddrFamily<family>::addr>(
367726f2bddSWilliam A. Kennington III                 std::get<std::string>(neighbor.at("IPAddress"))));
368726f2bddSWilliam A. Kennington III         }
369726f2bddSWilliam A. Kennington III         catch (...)
3708a7236aeSJohn Wang         {
3718a7236aeSJohn Wang             continue;
3728a7236aeSJohn Wang         }
373726f2bddSWilliam A. Kennington III         if (*neighIP != ip)
3748a7236aeSJohn Wang         {
3758a7236aeSJohn Wang             continue;
3768a7236aeSJohn Wang         }
3778a7236aeSJohn Wang         if (state != std::get<std::string>(neighbor.at("State")))
3788a7236aeSJohn Wang         {
3798a7236aeSJohn Wang             continue;
3808a7236aeSJohn Wang         }
3818a7236aeSJohn Wang 
3828a7236aeSJohn Wang         IfNeigh<family> ret;
3838a7236aeSJohn Wang         ret.path = path;
3848a7236aeSJohn Wang         ret.ip = ip;
385726f2bddSWilliam A. Kennington III         ret.mac = stdplus::fromStr<stdplus::EtherAddr>(
386726f2bddSWilliam A. Kennington III             std::get<std::string>(neighbor.at("MACAddress")));
38711d68897SWilly Tu         return ret;
3888a7236aeSJohn Wang     }
3898a7236aeSJohn Wang 
3908a7236aeSJohn Wang     return std::nullopt;
3918a7236aeSJohn Wang }
3928a7236aeSJohn Wang 
3938a7236aeSJohn Wang template <int family>
createNeighbor(sdbusplus::bus_t & bus,const ChannelParams & params,typename AddrFamily<family>::addr address,stdplus::EtherAddr mac)3945d82f474SPatrick Williams void createNeighbor(sdbusplus::bus_t& bus, const ChannelParams& params,
395726f2bddSWilliam A. Kennington III                     typename AddrFamily<family>::addr address,
396726f2bddSWilliam A. Kennington III                     stdplus::EtherAddr mac)
3978a7236aeSJohn Wang {
398fbc6c9d7SPatrick Williams     auto newreq = bus.new_method_call(params.service.c_str(),
399fbc6c9d7SPatrick Williams                                       params.logicalPath.c_str(),
4008a7236aeSJohn Wang                                       INTF_NEIGHBOR_CREATE_STATIC, "Neighbor");
401726f2bddSWilliam A. Kennington III     stdplus::ToStrHandle<stdplus::ToStr<stdplus::EtherAddr>> macToStr;
402726f2bddSWilliam A. Kennington III     stdplus::ToStrHandle<stdplus::ToStr<typename AddrFamily<family>::addr>>
403726f2bddSWilliam A. Kennington III         addrToStr;
404726f2bddSWilliam A. Kennington III     newreq.append(addrToStr(address), macToStr(mac));
4058a7236aeSJohn Wang     bus.call_noreply(newreq);
4068a7236aeSJohn Wang }
4078a7236aeSJohn Wang 
4088a7236aeSJohn Wang /** @brief Deletes the dbus object. Ignores empty objects or objects that are
4098a7236aeSJohn Wang  *         missing from the bus.
4108a7236aeSJohn Wang  *
4118a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
4128a7236aeSJohn Wang  *  @param[in] service - The name of the service
4138a7236aeSJohn Wang  *  @param[in] path    - The path of the object to delete
4148a7236aeSJohn Wang  */
4155d82f474SPatrick Williams void deleteObjectIfExists(sdbusplus::bus_t& bus, const std::string& service,
4168a7236aeSJohn Wang                           const std::string& path);
4178a7236aeSJohn Wang 
418d1bd8c48SLei YU /** @brief Sets the value for the default gateway of the channel
4198a7236aeSJohn Wang  *
4208a7236aeSJohn Wang  *  @param[in] bus     - The bus object used for lookups
4218a7236aeSJohn Wang  *  @param[in] params  - The parameters for the channel
4228a7236aeSJohn Wang  *  @param[in] gateway - Gateway address to apply
4238a7236aeSJohn Wang  */
4248a7236aeSJohn Wang template <int family>
setGatewayProperty(sdbusplus::bus_t & bus,const ChannelParams & params,typename AddrFamily<family>::addr address)4255d82f474SPatrick Williams void setGatewayProperty(sdbusplus::bus_t& bus, const ChannelParams& params,
426726f2bddSWilliam A. Kennington III                         typename AddrFamily<family>::addr address)
4278a7236aeSJohn Wang {
4288a7236aeSJohn Wang     // Save the old gateway MAC address if it exists so we can recreate it
4298a7236aeSJohn Wang     auto gateway = getGatewayProperty<family>(bus, params);
4308a7236aeSJohn Wang     std::optional<IfNeigh<family>> neighbor;
4318a7236aeSJohn Wang     if (gateway)
4328a7236aeSJohn Wang     {
4338a7236aeSJohn Wang         ObjectLookupCache neighbors(bus, params, INTF_NEIGHBOR);
4348a7236aeSJohn Wang         neighbor = findStaticNeighbor<family>(bus, params, *gateway, neighbors);
4358a7236aeSJohn Wang     }
4368a7236aeSJohn Wang 
437d1bd8c48SLei YU     auto objPath = "/xyz/openbmc_project/network/" + params.ifname;
438d1bd8c48SLei YU     setDbusProperty(bus, params.service, objPath, INTF_ETHERNET,
4398a7236aeSJohn Wang                     AddrFamily<family>::propertyGateway,
440726f2bddSWilliam A. Kennington III                     stdplus::toStr(address));
4418a7236aeSJohn Wang 
4428a7236aeSJohn Wang     // Restore the gateway MAC if we had one
4438a7236aeSJohn Wang     if (neighbor)
4448a7236aeSJohn Wang     {
4458a7236aeSJohn Wang         deleteObjectIfExists(bus, params.service, neighbor->path);
4468a7236aeSJohn Wang         createNeighbor<family>(bus, params, address, neighbor->mac);
4478a7236aeSJohn Wang     }
4488a7236aeSJohn Wang }
4498a7236aeSJohn Wang 
450690a2342SPatrick Venture } // namespace transport
451690a2342SPatrick Venture } // namespace ipmi
452