xref: /openbmc/phosphor-networkd/test/test_ethernet_interface.cpp (revision 454a0dee8c334bea393d9723147cc4f78d0f1dc1)
1 #include "config_parser.hpp"
2 #include "ipaddress.hpp"
3 #include "mock_network_manager.hpp"
4 #include "mock_syscall.hpp"
5 #include "system_queries.hpp"
6 #include "util.hpp"
7 
8 #include <arpa/inet.h>
9 #include <net/if.h>
10 #include <netinet/in.h>
11 #include <stdlib.h>
12 
13 #include <charconv>
14 #include <exception>
15 #include <sdbusplus/bus.hpp>
16 #include <stdplus/gtest/tmp.hpp>
17 #include <string_view>
18 #include <xyz/openbmc_project/Common/error.hpp>
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 namespace phosphor
24 {
25 namespace network
26 {
27 
28 using std::literals::string_view_literals::operator""sv;
29 using testing::Key;
30 using testing::UnorderedElementsAre;
31 
32 class TestEthernetInterface : public stdplus::gtest::TestWithTmp
33 {
34   public:
35     sdbusplus::bus_t bus;
36     std::string confDir;
37     MockManager manager;
38     MockEthernetInterface interface;
39     TestEthernetInterface() :
40         bus(sdbusplus::bus::new_default()), confDir(CaseTmpDir()),
41         manager(bus, "/xyz/openbmc_test/network", confDir),
42         interface(makeInterface(bus, manager))
43 
44     {
45     }
46 
47     static MockEthernetInterface makeInterface(sdbusplus::bus_t& bus,
48                                                MockManager& manager)
49     {
50         system::mock_clear();
51         InterfaceInfo info{.idx = 1, .flags = 0, .name = "test0"};
52         system::mock_addIF(info);
53         return {bus, manager, info, "/xyz/openbmc_test/network"sv,
54                 config::Parser()};
55     }
56 
57     auto createIPObject(IP::Protocol addressType, const std::string& ipaddress,
58                         uint8_t subnetMask)
59     {
60         return interface.ip(addressType, ipaddress, subnetMask, "");
61     }
62 
63     void setNtpServers()
64     {
65         ServerList ntpServers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
66         interface.EthernetInterfaceIntf::ntpServers(ntpServers);
67     }
68 
69     ServerList getNtpServers()
70     {
71         return interface.EthernetInterfaceIntf::ntpServers();
72     }
73 };
74 
75 TEST_F(TestEthernetInterface, Fields)
76 {
77     EXPECT_EQ(0, interface.mtu());
78     EXPECT_EQ("", interface.macAddress());
79     EXPECT_FALSE(interface.linkUp());
80 
81     constexpr ether_addr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
82     constexpr unsigned mtu = 150;
83 
84     InterfaceInfo info{.idx = 2,
85                        .flags = IFF_RUNNING,
86                        .name = "test1",
87                        .mac = mac,
88                        .mtu = mtu};
89     system::mock_addIF(info);
90     MockEthernetInterface intf(bus, manager, info,
91                                "/xyz/openbmc_test/network"sv, config::Parser());
92 
93     EXPECT_EQ(mtu, intf.mtu());
94     EXPECT_EQ(std::to_string(mac), intf.macAddress());
95     EXPECT_TRUE(intf.linkUp());
96 }
97 
98 TEST_F(TestEthernetInterface, NoIPaddress)
99 {
100     EXPECT_TRUE(interface.addrs.empty());
101 }
102 
103 TEST_F(TestEthernetInterface, AddIPAddress)
104 {
105     createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
106     EXPECT_THAT(interface.addrs, UnorderedElementsAre(Key(
107                                      IfAddr(in_addr{htonl(0x0a0a0a0a)}, 16))));
108 }
109 
110 TEST_F(TestEthernetInterface, AddMultipleAddress)
111 {
112     createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
113     createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
114     EXPECT_THAT(
115         interface.addrs,
116         UnorderedElementsAre(Key(IfAddr(in_addr{htonl(0x0a0a0a0a)}, 16)),
117                              Key(IfAddr(in_addr{htonl(0x14141414)}, 16))));
118 }
119 
120 TEST_F(TestEthernetInterface, DeleteIPAddress)
121 {
122     createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
123     createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
124     interface.addrs.at(IfAddr(in_addr{htonl(0x0a0a0a0a)}, 16))->delete_();
125     EXPECT_THAT(interface.addrs, UnorderedElementsAre(Key(
126                                      IfAddr(in_addr{htonl(0x14141414)}, 16))));
127 }
128 
129 TEST_F(TestEthernetInterface, CheckObjectPath)
130 {
131     auto path = createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
132     EXPECT_EQ(path.parent_path(), "/xyz/openbmc_test/network/test0");
133     EXPECT_EQ(path.filename(), "10.10.10.10/16");
134 }
135 
136 TEST_F(TestEthernetInterface, addStaticNameServers)
137 {
138     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
139     EXPECT_CALL(manager, reloadConfigsNoRefresh());
140     interface.staticNameServers(servers);
141     fs::path filePath = confDir;
142     filePath /= "00-bmc-test0.network";
143     config::Parser parser(filePath.string());
144     EXPECT_EQ(servers, parser.map.getValueStrings("Network", "DNS"));
145 }
146 
147 TEST_F(TestEthernetInterface, getDynamicNameServers)
148 {
149     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
150     EXPECT_CALL(interface, getNameServerFromResolvd())
151         .WillRepeatedly(testing::Return(servers));
152     EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
153 }
154 
155 TEST_F(TestEthernetInterface, addStaticNTPServers)
156 {
157     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
158     EXPECT_CALL(manager, reloadConfigsNoRefresh());
159     interface.staticNTPServers(servers);
160     fs::path filePath = confDir;
161     filePath /= "00-bmc-test0.network";
162     config::Parser parser(filePath.string());
163     EXPECT_EQ(servers, parser.map.getValueStrings("Network", "NTP"));
164 }
165 
166 TEST_F(TestEthernetInterface, addNTPServers)
167 {
168     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
169     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
170     EXPECT_THROW(interface.ntpServers(servers), NotAllowed);
171 }
172 
173 TEST_F(TestEthernetInterface, getNTPServers)
174 {
175     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
176     setNtpServers();
177     EXPECT_EQ(getNtpServers(), servers);
178 }
179 
180 TEST_F(TestEthernetInterface, addGateway)
181 {
182     std::string gateway = "10.3.3.3";
183     interface.defaultGateway(gateway);
184     EXPECT_EQ(interface.defaultGateway(), gateway);
185     interface.defaultGateway("");
186     EXPECT_EQ(interface.defaultGateway(), "");
187 }
188 
189 TEST_F(TestEthernetInterface, addGateway6)
190 {
191     std::string gateway6 = "ffff:ffff:ffff:fe80::1";
192     interface.defaultGateway6(gateway6);
193     EXPECT_EQ(interface.defaultGateway6(), gateway6);
194     interface.defaultGateway6("");
195     EXPECT_EQ(interface.defaultGateway6(), "");
196 }
197 
198 TEST_F(TestEthernetInterface, DHCPEnabled)
199 {
200     EXPECT_CALL(manager, reloadConfigs()).WillRepeatedly(testing::Return());
201 
202     using DHCPConf = EthernetInterfaceIntf::DHCPConf;
203     auto test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
204         EXPECT_EQ(conf, interface.dhcpEnabled());
205         EXPECT_EQ(dhcp4, interface.dhcp4());
206         EXPECT_EQ(dhcp6, interface.dhcp6());
207         EXPECT_EQ(ra, interface.ipv6AcceptRA());
208     };
209     test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
210 
211     auto set_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
212         EXPECT_EQ(conf, interface.dhcpEnabled(conf));
213         test(conf, dhcp4, dhcp6, ra);
214     };
215     set_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
216     set_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
217     set_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
218              /*ra=*/true);
219     set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
220     set_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
221              /*ra=*/true);
222     set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
223 
224     auto ind_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
225         EXPECT_EQ(dhcp4, interface.dhcp4(dhcp4));
226         EXPECT_EQ(dhcp6, interface.dhcp6(dhcp6));
227         EXPECT_EQ(ra, interface.ipv6AcceptRA(ra));
228         test(conf, dhcp4, dhcp6, ra);
229     };
230     ind_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
231     ind_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
232     ind_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
233              /*ra=*/true);
234     ind_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/false);
235     set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
236     ind_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
237              /*ra=*/true);
238     ind_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/false);
239     set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
240 }
241 
242 } // namespace network
243 } // namespace phosphor
244