summaryrefslogtreecommitdiffstats
path: root/test/test_rtnetlink.cpp
blob: 92846005ed71d8468ecdd902db39bed68e3bd125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#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
OpenPOWER on IntegriCloud