| #include "mock_network_manager.hpp" |
| #include "mock_syscall.hpp" |
| #include "rtnetlink_server.hpp" |
| #include "types.hpp" |
| |
| #include <linux/rtnetlink.h> |
| #include <net/if.h> |
| |
| #include <chrono> |
| #include <functional> |
| #include <sdbusplus/bus.hpp> |
| #include <sdeventplus/event.hpp> |
| |
| #include <gtest/gtest.h> |
| |
| namespace phosphor |
| { |
| |
| namespace network |
| { |
| sdbusplus::bus::bus bus(sdbusplus::bus::new_default()); |
| std::unique_ptr<MockManager> manager = nullptr; |
| extern std::unique_ptr<Timer> refreshObjectTimer; |
| extern std::unique_ptr<Timer> restartTimer; |
| EventPtr eventPtr = nullptr; |
| |
| /** @brief refresh the network objects. */ |
| void refreshObjects() |
| { |
| |
| if (manager) |
| { |
| manager->createChildObjects(); |
| } |
| } |
| |
| void initializeTimers() |
| { |
| refreshObjectTimer = std::make_unique<Timer>( |
| sdeventplus::Event::get_default(), std::bind(refreshObjects)); |
| } |
| |
| class TestRtNetlink : public testing::Test |
| { |
| |
| public: |
| std::string confDir; |
| phosphor::Descriptor smartSock; |
| |
| TestRtNetlink() |
| { |
| manager = |
| std::make_unique<MockManager>(bus, "/xyz/openbmc_test/bcd", "/tmp"); |
| sd_event* events; |
| sd_event_default(&events); |
| eventPtr.reset(events); |
| events = nullptr; |
| setConfDir(); |
| initializeTimers(); |
| createNetLinkSocket(); |
| bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL); |
| rtnetlink::Server svr(eventPtr, smartSock); |
| } |
| |
| ~TestRtNetlink() |
| { |
| if (confDir.empty()) |
| { |
| fs::remove_all(confDir); |
| } |
| } |
| |
| void setConfDir() |
| { |
| char tmp[] = "/tmp/NetworkManager.XXXXXX"; |
| confDir = mkdtemp(tmp); |
| manager->setConfDir(confDir); |
| } |
| |
| bool isInterfaceAdded(std::string intf) |
| { |
| return manager->interfaces.find(intf) != manager->interfaces.end() |
| ? true |
| : false; |
| } |
| |
| void createNetLinkSocket() |
| { |
| // RtnetLink socket |
| auto fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE); |
| smartSock.set(fd); |
| } |
| }; |
| |
| TEST_F(TestRtNetlink, WithSingleInterface) |
| { |
| using namespace std::chrono; |
| // Adds the following ip in the getifaddrs list. |
| mock_addIP("igb5", "127.0.0.1", "255.255.255.128", IFF_UP | IFF_RUNNING); |
| constexpr auto BUFSIZE = 4096; |
| std::array<char, BUFSIZE> msgBuf = {0}; |
| |
| // point the header and the msg structure pointers into the buffer. |
| auto nlMsg = reinterpret_cast<nlmsghdr*>(msgBuf.data()); |
| // Length of message |
| nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); |
| nlMsg->nlmsg_type = RTM_GETADDR; |
| nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; |
| nlMsg->nlmsg_seq = 0; |
| nlMsg->nlmsg_pid = getpid(); |
| |
| EXPECT_EQ(false, isInterfaceAdded("igb5")); |
| // Send the request |
| send(smartSock(), nlMsg, nlMsg->nlmsg_len, 0); |
| |
| int i = 3; |
| while (i--) |
| { |
| // wait for timer to expire |
| std::this_thread::sleep_for(std::chrono::milliseconds(refreshTimeout)); |
| sd_event_run(eventPtr.get(), 10); |
| }; |
| |
| EXPECT_EQ(true, isInterfaceAdded("igb5")); |
| } |
| |
| } // namespace network |
| } // namespace phosphor |