ethernet_interface: Refactor object hashing
Change-Id: Ic1022410fea18be5508c8fa08a27e4ae1a2d51e0
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index fc1e6b0..b891401 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -19,7 +19,6 @@
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus/match.hpp>
-#include <sstream>
#include <stdplus/fd/create.hpp>
#include <stdplus/raw.hpp>
#include <stdplus/zstring.hpp>
@@ -38,6 +37,7 @@
using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
using Argument = xyz::openbmc_project::Common::InvalidArgument;
+using std::literals::string_view_literals::operator""sv;
constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
@@ -380,32 +380,6 @@
stdplus::raw::refFrom<ether_addr>(ifr.ifr_hwaddr.sa_data));
}
-std::string EthernetInterface::generateId(std::string_view ipaddress,
- uint8_t prefixLength,
- std::string_view origin)
-{
- std::stringstream hexId;
- std::string hashString = std::string(ipaddress);
- hashString += std::to_string(prefixLength);
- hashString += origin;
-
- // Only want 8 hex digits.
- hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
- return hexId.str();
-}
-
-std::string EthernetInterface::generateNeighborId(std::string_view ipAddress,
- std::string_view macAddress)
-{
- std::stringstream hexId;
- std::string hashString = std::string(ipAddress);
- hashString += macAddress;
-
- // Only want 8 hex digits.
- hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
- return hexId.str();
-}
-
void EthernetInterface::deleteObject(std::string_view ipaddress)
{
auto it = addrs.find(ipaddress);
@@ -478,29 +452,32 @@
}
std::string EthernetInterface::generateObjectPath(
- IP::Protocol addressType, std::string_view ipaddress, uint8_t prefixLength,
+ IP::Protocol addressType, std::string_view ipAddress, uint8_t prefixLength,
IP::AddressOrigin origin) const
{
- std::string type = convertForMessage(addressType);
- type = type.substr(type.rfind('.') + 1);
- std::transform(type.begin(), type.end(), type.begin(), ::tolower);
-
- std::filesystem::path objectPath;
- objectPath /= objPath;
- objectPath /= type;
- objectPath /=
- generateId(ipaddress, prefixLength, convertForMessage(origin));
- return objectPath.string();
+ std::string_view type;
+ switch (addressType)
+ {
+ case IP::Protocol::IPv4:
+ type = "ipv4"sv;
+ break;
+ case IP::Protocol::IPv6:
+ type = "ipv6"sv;
+ break;
+ }
+ return fmt::format(
+ FMT_COMPILE("{}/{}/{:08x}"), objPath, type,
+ static_cast<uint32_t>(hash_multi(
+ ipAddress, prefixLength,
+ static_cast<std::underlying_type_t<IP::AddressOrigin>>(origin))));
}
std::string EthernetInterface::generateStaticNeighborObjectPath(
std::string_view ipAddress, std::string_view macAddress) const
{
- std::filesystem::path objectPath;
- objectPath /= objPath;
- objectPath /= "static_neighbor";
- objectPath /= generateNeighborId(ipAddress, macAddress);
- return objectPath.string();
+ return fmt::format(
+ FMT_COMPILE("{}/static_neighbor/{:08x}"), objPath,
+ static_cast<uint32_t>(hash_multi(ipAddress, macAddress)));
}
bool EthernetInterface::ipv6AcceptRA(bool value)
diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
index deada56..a9b1bbd 100644
--- a/src/ethernet_interface.hpp
+++ b/src/ethernet_interface.hpp
@@ -262,7 +262,6 @@
* @return path of the address object.
*/
-
std::string generateObjectPath(IP::Protocol addressType,
std::string_view ipAddress,
uint8_t prefixLength,
@@ -272,26 +271,6 @@
generateStaticNeighborObjectPath(std::string_view ipAddress,
std::string_view macAddress) const;
- /** @brief generates the id by doing hash of ipAddress and prefixLength
- * @param[in] ipAddress - IP address.
- * @param[in] prefixLength - Length of prefix.
- * @param[in] origin - The string of the address origin
- * @return hash string.
- */
-
- static std::string generateId(std::string_view ipAddress,
- uint8_t prefixLength,
- std::string_view origin);
-
- /** @brief generates the id by doing hash of ipAddress
- * and the mac address.
- * @param[in] ipAddress - IP address.
- * @param[in] macAddress - Gateway address.
- * @return hash string.
- */
- static std::string generateNeighborId(std::string_view ipAddress,
- std::string_view macAddress);
-
/** @brief get the NTP server list from the network conf
*
*/
diff --git a/src/types.hpp b/src/types.hpp
index 58ad04a..9eeb3b7 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -64,5 +64,17 @@
using string_uset =
std::unordered_set<std::string, string_hash, std::equal_to<>>;
+constexpr std::size_t hash_multi()
+{
+ return 0;
+}
+
+template <typename T, typename... Args>
+constexpr std::size_t hash_multi(const T& v, Args... args)
+{
+ const std::size_t seed = hash_multi(args...);
+ return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+}
+
} // namespace network
} // namespace phosphor
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index 4f2b204..497eaa0 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -9,10 +9,11 @@
#include <netinet/in.h>
#include <stdlib.h>
+#include <charconv>
#include <exception>
-#include <fstream>
#include <sdbusplus/bus.hpp>
#include <stdplus/gtest/tmp.hpp>
+#include <string_view>
#include <gtest/gtest.h>
@@ -21,6 +22,8 @@
namespace network
{
+using std::literals::string_view_literals::operator""sv;
+
class TestEthernetInterface : public stdplus::gtest::TestWithTmp
{
public:
@@ -132,20 +135,19 @@
uint8_t prefix = 16;
IP::AddressOrigin origin = IP::AddressOrigin::Static;
- std::string expectedObjectPath = "/xyz/openbmc_test/network/test0/ipv4/";
- std::stringstream hexId;
+ auto path = getObjectPath(ipaddress, prefix, origin);
+ auto pathsv = std::string_view(path);
+ constexpr auto expectedPrefix = "/xyz/openbmc_test/network/test0/ipv4/"sv;
+ EXPECT_TRUE(pathsv.starts_with(expectedPrefix));
+ pathsv.remove_prefix(expectedPrefix.size());
+ uint32_t val;
+ auto [ptr, res] = std::from_chars(pathsv.begin(), pathsv.end(), val, 16);
+ EXPECT_EQ(res, std::errc());
+ EXPECT_EQ(ptr, pathsv.end());
- std::string hashString = ipaddress;
- hashString += std::to_string(prefix);
- hashString += convertForMessage(origin);
-
- hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
- expectedObjectPath += hexId.str();
-
- EXPECT_EQ(expectedObjectPath, getObjectPath(ipaddress, prefix, origin));
-
+ EXPECT_EQ(path, getObjectPath(ipaddress, prefix, origin));
origin = IP::AddressOrigin::DHCP;
- EXPECT_NE(expectedObjectPath, getObjectPath(ipaddress, prefix, origin));
+ EXPECT_NE(path, getObjectPath(ipaddress, prefix, origin));
}
TEST_F(TestEthernetInterface, addStaticNameServers)