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