xref: /openbmc/phosphor-networkd/test/test_ethernet_interface.cpp (revision af77f827b6b33a3c0834565bd168653e4897fe19)
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 stdplus::EtherAddr 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(stdplus::toStr(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(stdplus::SubnetAny(
100                                      stdplus::In4Addr{10, 10, 10, 10}, 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(
110             Key(stdplus::SubnetAny(stdplus::In4Addr{10, 10, 10, 10}, 16)),
111             Key(stdplus::SubnetAny(stdplus::In4Addr{20, 20, 20, 20}, 16))));
112 }
113 
114 TEST_F(TestEthernetInterface, DeleteIPAddress)
115 {
116     createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
117     createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
118     interface.addrs
119         .at(stdplus::SubnetAny(stdplus::In4Addr{10, 10, 10, 10}, 16))
120         ->delete_();
121     EXPECT_THAT(interface.addrs, UnorderedElementsAre(Key(stdplus::SubnetAny(
122                                      stdplus::In4Addr{20, 20, 20, 20}, 16))));
123 }
124 
125 TEST_F(TestEthernetInterface, CheckObjectPath)
126 {
127     auto path = createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
128     EXPECT_EQ(path.parent_path(), "/xyz/openbmc_test/network/test0");
129     EXPECT_EQ(path.filename(), "10.10.10.10/16");
130 }
131 
132 TEST_F(TestEthernetInterface, addStaticNameServers)
133 {
134     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
135     EXPECT_CALL(manager.mockReload, schedule());
136     interface.staticNameServers(servers);
137     config::Parser parser((confDir / "00-bmc-test0.network").native());
138     EXPECT_EQ(servers, parser.map.getValueStrings("Network", "DNS"));
139 }
140 
141 TEST_F(TestEthernetInterface, getDynamicNameServers)
142 {
143     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
144     EXPECT_CALL(interface, getNameServerFromResolvd())
145         .WillRepeatedly(testing::Return(servers));
146     EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
147 }
148 
149 TEST_F(TestEthernetInterface, addStaticNTPServers)
150 {
151     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
152     EXPECT_CALL(manager.mockReload, schedule());
153     interface.staticNTPServers(servers);
154     config::Parser parser((confDir / "00-bmc-test0.network").native());
155     EXPECT_EQ(servers, parser.map.getValueStrings("Network", "NTP"));
156 }
157 
158 TEST_F(TestEthernetInterface, addNTPServers)
159 {
160     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
161     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
162     EXPECT_THROW(interface.ntpServers(servers), NotAllowed);
163 }
164 
165 TEST_F(TestEthernetInterface, getNTPServers)
166 {
167     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
168     setNtpServers();
169     EXPECT_EQ(getNtpServers(), servers);
170 }
171 
172 TEST_F(TestEthernetInterface, addGateway)
173 {
174     std::string gateway = "10.3.3.3";
175     interface.defaultGateway(gateway);
176     EXPECT_EQ(interface.defaultGateway(), gateway);
177     interface.defaultGateway("");
178     EXPECT_EQ(interface.defaultGateway(), "");
179 }
180 
181 TEST_F(TestEthernetInterface, addGateway6)
182 {
183     std::string gateway6 = "ffff:ffff:ffff:fe80::1";
184     interface.defaultGateway6(gateway6);
185     EXPECT_EQ(interface.defaultGateway6(), gateway6);
186     interface.defaultGateway6("");
187     EXPECT_EQ(interface.defaultGateway6(), "");
188 }
189 
190 TEST_F(TestEthernetInterface, DHCPEnabled)
191 {
192     EXPECT_CALL(manager.mockReload, schedule())
193         .WillRepeatedly(testing::Return());
194 
195     using DHCPConf = EthernetInterfaceIntf::DHCPConf;
196     auto test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
197         EXPECT_EQ(conf, interface.dhcpEnabled());
198         EXPECT_EQ(dhcp4, interface.dhcp4());
199         EXPECT_EQ(dhcp6, interface.dhcp6());
200         EXPECT_EQ(ra, interface.ipv6AcceptRA());
201     };
202     test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
203 
204     auto set_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
205         EXPECT_EQ(conf, interface.dhcpEnabled(conf));
206         test(conf, dhcp4, dhcp6, ra);
207     };
208     set_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
209     set_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
210     set_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
211              /*ra=*/true);
212     set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
213     set_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
214              /*ra=*/true);
215     set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
216 
217     auto ind_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
218         EXPECT_EQ(dhcp4, interface.dhcp4(dhcp4));
219         EXPECT_EQ(dhcp6, interface.dhcp6(dhcp6));
220         EXPECT_EQ(ra, interface.ipv6AcceptRA(ra));
221         test(conf, dhcp4, dhcp6, ra);
222     };
223     ind_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
224     ind_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
225     ind_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
226              /*ra=*/true);
227     ind_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/false);
228     set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
229     ind_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
230              /*ra=*/true);
231     ind_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/false);
232     set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
233 }
234 
235 } // namespace network
236 } // namespace phosphor
237