vlan: implement delete interface
Delete the in-memory vlan object,Also
deletes the associated device file and the
network file.
Change-Id: I613e31aaa4fa9172c6226765ac044481ffbd88ec
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
index 30927f6..5eb6aa7 100644
--- a/ethernet_interface.cpp
+++ b/ethernet_interface.cpp
@@ -275,6 +275,56 @@
writeConfigurationFile();
}
+void EthernetInterface::deleteVLANObject(const std::string& interface)
+{
+ using namespace std::string_literals;
+
+ auto it = vlanInterfaces.find(interface);
+ if (it == vlanInterfaces.end())
+ {
+ log<level::ERR>("DeleteVLANObject:Unable to find the object",
+ entry("INTERFACE=%s",interface.c_str()));
+ return;
+ }
+
+ auto confDir = manager.getConfDir();
+ fs::path networkFile = confDir;
+ networkFile /= systemd::config::networkFilePrefix + interface +
+ systemd::config::networkFileSuffix;
+
+ fs::path deviceFile = confDir;
+ deviceFile /= interface + systemd::config::deviceFileSuffix;
+
+ // delete the vlan network file
+ if (fs::is_regular_file(networkFile))
+ {
+ fs::remove(networkFile);
+ }
+
+ // delete the vlan device file
+ if (fs::is_regular_file(deviceFile))
+ {
+ fs::remove(deviceFile);
+ }
+ // delete the interface
+ vlanInterfaces.erase(it);
+ // restart the systemd-networkd
+
+ restartSystemdUnit("systemd-networkd.service");
+
+ // TODO systemd doesn't delete the virtual network interface
+ // even after deleting all the related configuartion.
+ // https://github.com/systemd/systemd/issues/6600
+ try
+ {
+ deleteInterface(interface);
+ }
+ catch (InternalFailure& e)
+ {
+ commit<InternalFailure>();
+ }
+}
+
std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
const std::string& ipaddress,
uint8_t prefixLength,
@@ -371,7 +421,8 @@
namespace fs = std::experimental::filesystem;
fs::path confPath = manager.getConfDir();
- std::string fileName = "00-bmc-"s + interfaceName() + ".network"s;
+ std::string fileName = systemd::config::networkFilePrefix + interfaceName() +
+ systemd::config::networkFileSuffix;
confPath /= fileName;
std::fstream stream;
diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
index 36669d6..29d377e 100644
--- a/ethernet_interface.hpp
+++ b/ethernet_interface.hpp
@@ -9,7 +9,6 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
-
#include <string>
#include <experimental/filesystem>
@@ -94,6 +93,12 @@
*/
void deleteObject(const std::string& ipaddress);
+ /* @brief delete the vlan dbus object of the given interface.
+ * Also deletes the device file and the network file.
+ * @param[in] interface - VLAN Interface.
+ */
+ void deleteVLANObject(const std::string& interface);
+
/* @brief creates the dbus object(IPaddres) given in the address list.
* @param[in] addrs - address list for which dbus objects needs
* to create.
diff --git a/types.hpp b/types.hpp
index ca35421..eb1f9fe 100644
--- a/types.hpp
+++ b/types.hpp
@@ -12,6 +12,17 @@
{
namespace network
{
+namespace systemd
+{
+namespace config
+{
+
+constexpr auto networkFilePrefix = "00-bmc-";
+constexpr auto networkFileSuffix = ".network";
+constexpr auto deviceFileSuffix = ".netdev";
+
+}// namespace config
+}// namespace systemd
using IntfName = std::string;
diff --git a/util.cpp b/util.cpp
index 64a913c..d96fe97 100644
--- a/util.cpp
+++ b/util.cpp
@@ -8,6 +8,7 @@
#include <arpa/inet.h>
#include <dirent.h>
#include <net/if.h>
+#include <sys/wait.h>
#include <iostream>
#include <list>
@@ -18,6 +19,7 @@
{
namespace network
{
+
namespace
{
@@ -52,7 +54,7 @@
if (sscanf(str.c_str(), "%hx", &buff) <= 0)
{
log<level::ERR>("Invalid Mask",
- entry("SUBNETMASK=%s", subnetMask));
+ entry("SUBNETMASK=%s", subnetMask));
return 0;
}
@@ -140,7 +142,7 @@
}
std::string getNetworkID(int addressFamily, const std::string& ipaddress,
- uint8_t prefix)
+ uint8_t prefix)
{
unsigned char* pntMask = nullptr;
unsigned char* pntNetwork = nullptr;
@@ -171,7 +173,7 @@
if (inet_pton(addressFamily, ipaddress.c_str(), &ipaddressNetwork) <= 0)
{
log<level::ERR>("inet_pton failure",
- entry("IPADDRESS=%s",ipaddress.c_str()));
+ entry("IPADDRESS=%s", ipaddress.c_str()));
report<InternalFailure>();
return "";
@@ -202,13 +204,13 @@
std::string linklocal = "fe80";
return std::mismatch(linklocal.begin(), linklocal.end(),
address.begin()).first == linklocal.end() ?
- true : false;
+ true : false;
}
IntfAddrMap getInterfaceAddrs()
{
- IntfAddrMap intfMap{};
- AddrList addrList{};
+ IntfAddrMap intfMap {};
+ AddrList addrList {};
struct ifaddrs* ifaddr = nullptr;
// attempt to fill struct with ifaddrs
@@ -223,7 +225,7 @@
AddrPtr ifaddrPtr(ifaddr);
ifaddr = nullptr;
- std::string intfName{};
+ std::string intfName {};
for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
{
@@ -252,7 +254,7 @@
addrList.clear();
}
intfName = ifa->ifa_name;
- AddrInfo info{};
+ AddrInfo info {};
char ip[INET6_ADDRSTRLEN] = { 0 };
char subnetMask[INET6_ADDRSTRLEN] = { 0 };
@@ -294,5 +296,48 @@
return intfMap;
}
+void deleteInterface(const std::string& 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>();
+ }
+ }
+}
+
}//namespace network
}//namespace phosphor
diff --git a/util.hpp b/util.hpp
index 3434aca..1d74300 100644
--- a/util.hpp
+++ b/util.hpp
@@ -63,6 +63,12 @@
}
+/** @brief Delete the given interface.
+ * @param[in] intf - interface name.
+ */
+void deleteInterface(const std::string& intf);
+
+
} //namespace network
class Descriptor
diff --git a/vlan_interface.cpp b/vlan_interface.cpp
index f4224d4..88e3c10 100644
--- a/vlan_interface.cpp
+++ b/vlan_interface.cpp
@@ -26,14 +26,14 @@
uint32_t vlanID,
EthernetInterface& intf,
Manager& parent ) :
- VlanIntfObject(bus, objPath.c_str(), true),
+ Interfaces(bus, objPath.c_str(), true),
EthernetInterface(bus, objPath, dhcpEnabled, parent, false),
parentInterface(intf)
{
id(vlanID);
VlanIface::interfaceName(EthernetInterface::interfaceName());
- VlanIntfObject::emit_object_added();
+ Interfaces::emit_object_added();
}
void VlanInterface::writeDeviceFile()
@@ -64,5 +64,10 @@
stream.close();
}
+void VlanInterface::delete_()
+{
+ parentInterface.deleteVLANObject(EthernetInterface::interfaceName());
+}
+
}//namespace network
}//namespace phosphor
diff --git a/vlan_interface.hpp b/vlan_interface.hpp
index c308611..3a06614 100644
--- a/vlan_interface.hpp
+++ b/vlan_interface.hpp
@@ -20,14 +20,16 @@
class Manager;
+using DeleteIface = sdbusplus::xyz::openbmc_project::Object::server::Delete;
using VlanIface = sdbusplus::xyz::openbmc_project::Network::server::VLAN;
-using VlanIntfObject = sdbusplus::server::object::object<VlanIface>;
+using Interfaces =
+ sdbusplus::server::object::object<DeleteIface, VlanIface>;
/** @class VlanInterface
* @brief OpenBMC vlan Interface implementation.
* @details A concrete implementation for the vlan interface
*/
-class VlanInterface : public VlanIntfObject, public EthernetInterface
+class VlanInterface : public Interfaces, public EthernetInterface
{
public:
VlanInterface() = delete;
@@ -52,6 +54,10 @@
EthernetInterface& intf,
Manager& manager);
+ /** @brief Delete this d-bus object.
+ */
+ void delete_() override;
+
/** @brief writes the device configuration.
systemd reads this configuration file
and creates the vlan interface.*/