1 #include "mock_network_manager.hpp"
2 #include "mock_syscall.hpp"
3 #include "rtnetlink_server.hpp"
4 #include "types.hpp"
5 
6 #include <linux/rtnetlink.h>
7 #include <net/if.h>
8 
9 #include <chrono>
10 #include <functional>
11 #include <sdbusplus/bus.hpp>
12 #include <sdeventplus/event.hpp>
13 
14 #include <gtest/gtest.h>
15 
16 namespace phosphor
17 {
18 
19 namespace network
20 {
21 sdbusplus::bus::bus bus(sdbusplus::bus::new_default());
22 std::unique_ptr<MockManager> manager = nullptr;
23 extern std::unique_ptr<Timer> refreshObjectTimer;
24 extern std::unique_ptr<Timer> restartTimer;
25 EventPtr eventPtr = nullptr;
26 
27 /** @brief refresh the network objects. */
28 void refreshObjects()
29 {
30 
31     if (manager)
32     {
33         manager->createChildObjects();
34     }
35 }
36 
37 void initializeTimers()
38 {
39     refreshObjectTimer = std::make_unique<Timer>(
40         sdeventplus::Event::get_default(), std::bind(refreshObjects));
41 }
42 
43 class TestRtNetlink : public testing::Test
44 {
45 
46   public:
47     std::string confDir;
48     phosphor::Descriptor smartSock;
49 
50     TestRtNetlink()
51     {
52         manager =
53             std::make_unique<MockManager>(bus, "/xyz/openbmc_test/bcd", "/tmp");
54         sd_event* events;
55         sd_event_default(&events);
56         eventPtr.reset(events);
57         events = nullptr;
58         setConfDir();
59         initializeTimers();
60         createNetLinkSocket();
61         bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
62         rtnetlink::Server svr(eventPtr, smartSock);
63     }
64 
65     ~TestRtNetlink()
66     {
67         if (confDir.empty())
68         {
69             fs::remove_all(confDir);
70         }
71     }
72 
73     void setConfDir()
74     {
75         char tmp[] = "/tmp/NetworkManager.XXXXXX";
76         confDir = mkdtemp(tmp);
77         manager->setConfDir(confDir);
78     }
79 
80     void createNetLinkSocket()
81     {
82         // RtnetLink socket
83         auto fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
84         smartSock.set(fd);
85     }
86 };
87 
88 TEST_F(TestRtNetlink, WithSingleInterface)
89 {
90     using namespace std::chrono;
91     // Adds the following ip in the getifaddrs list.
92     mock_addIP("igb5", "127.0.0.1", "255.255.255.128", IFF_UP | IFF_RUNNING);
93     constexpr auto BUFSIZE = 4096;
94     std::array<char, BUFSIZE> msgBuf = {0};
95 
96     // point the header and the msg structure pointers into the buffer.
97     auto nlMsg = reinterpret_cast<nlmsghdr*>(msgBuf.data());
98     // Length of message
99     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
100     nlMsg->nlmsg_type = RTM_GETADDR;
101     nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
102     nlMsg->nlmsg_seq = 0;
103     nlMsg->nlmsg_pid = getpid();
104 
105     EXPECT_EQ(false, manager->hasInterface("igb5"));
106     // Send the request
107     send(smartSock(), nlMsg, nlMsg->nlmsg_len, 0);
108 
109     int i = 3;
110     while (i--)
111     {
112         // wait for timer to expire
113         std::this_thread::sleep_for(std::chrono::milliseconds(refreshTimeout));
114         sd_event_run(eventPtr.get(), 10);
115     };
116 
117     EXPECT_EQ(true, manager->hasInterface("igb5"));
118 }
119 
120 } // namespace network
121 } // namespace phosphor
122