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