system_queries: Add netlink based delete
We shouldn't depend on calling the IP binary
Change-Id: I4e9b3229ef936dad96e2fcfcea8f6b32a9c9f801
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index b57a24f..f480b2f 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -897,11 +897,11 @@
}
}
- // We need to forcibly delete the interface as systemd does not
- deleteInterface(intf);
-
if (eth.ifIdx > 0)
{
+ // We need to forcibly delete the interface as systemd does not
+ system::deleteIntf(eth.ifIdx);
+
eth.manager.interfacesByIdx.erase(eth.ifIdx);
}
eth.manager.interfaces.erase(intf);
diff --git a/src/system_queries.cpp b/src/system_queries.cpp
index 9a360bd..9a8cba8 100644
--- a/src/system_queries.cpp
+++ b/src/system_queries.cpp
@@ -1,7 +1,10 @@
#include "system_queries.hpp"
+#include "netlink.hpp"
+
#include <fmt/format.h>
#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>
@@ -109,4 +112,26 @@
getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
}
+void deleteIntf(unsigned idx)
+{
+ if (idx == 0)
+ {
+ return;
+ }
+ ifinfomsg msg = {};
+ msg.ifi_family = AF_UNSPEC;
+ msg.ifi_index = idx;
+ netlink::performRequest(
+ NETLINK_ROUTE, RTM_DELLINK, NLM_F_REPLACE, msg,
+ [&](const nlmsghdr& hdr, std::string_view data) {
+ int err = 0;
+ if (hdr.nlmsg_type == NLMSG_ERROR)
+ {
+ err = netlink::extractRtData<nlmsgerr>(data).error;
+ }
+ throw std::runtime_error(
+ fmt::format("Failed to delete `{}`: {}", idx, strerror(err)));
+ });
+}
+
} // namespace phosphor::network::system
diff --git a/src/system_queries.hpp b/src/system_queries.hpp
index 4c187c7..9027cb3 100644
--- a/src/system_queries.hpp
+++ b/src/system_queries.hpp
@@ -18,4 +18,6 @@
void setNICUp(std::string_view ifname, bool up);
+void deleteIntf(unsigned idx);
+
} // namespace phosphor::network::system
diff --git a/src/util.cpp b/src/util.cpp
index 5df9afa..938e4d4 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -129,47 +129,6 @@
} // namespace internal
-void deleteInterface(stdplus::const_zstring intf)
-{
- pid_t pid = fork();
- int status{};
-
- if (pid == 0)
- {
-
- execl("/sbin/ip", "ip", "link", "delete", "dev", intf.c_str(), nullptr);
- auto error = errno;
- log<level::ERR>("Couldn't delete the device", entry("ERRNO=%d", error),
- entry("INTF=%s", intf.c_str()));
- elog<InternalFailure>();
- }
- else if (pid < 0)
- {
- auto error = errno;
- log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", error));
- elog<InternalFailure>();
- }
- else if (pid > 0)
- {
- while (waitpid(pid, &status, 0) == -1)
- {
- if (errno != EINTR)
- { /* Error other than EINTR */
- status = -1;
- break;
- }
- }
-
- if (status < 0)
- {
- log<level::ERR>("Unable to delete the interface",
- entry("INTF=%s", intf.c_str()),
- entry("STATUS=%d", status));
- elog<InternalFailure>();
- }
- }
-}
-
std::optional<std::string> interfaceToUbootEthAddr(std::string_view intf)
{
constexpr auto pfx = "eth"sv;
diff --git a/src/util.hpp b/src/util.hpp
index 3638160..4cf27a0 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -74,11 +74,6 @@
throw std::invalid_argument("Unrecognized family");
}
-/** @brief Delete the given interface.
- * @param[in] intf - interface name.
- */
-void deleteInterface(stdplus::const_zstring intf);
-
/** @brief Converts the interface name into a u-boot environment
* variable that would hold its ethernet address.
*