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 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
23 using std::literals::string_view_literals::operator""sv;
24 using testing::Key;
25 using testing::UnorderedElementsAre;
26 using stdplus::operator""_sub;
27
28 class TestEthernetInterface : public stdplus::gtest::TestWithTmp
29 {
30 public:
31 stdplus::Pinned<sdbusplus::bus_t> bus;
32 std::filesystem::path confDir;
33 TestManager manager;
34 MockEthernetInterface interface;
TestEthernetInterface()35 TestEthernetInterface() :
36 bus(sdbusplus::bus::new_default()), confDir(CaseTmpDir()),
37 manager(bus, "/xyz/openbmc_test/network", confDir),
38 interface(makeInterface(bus, manager))
39
40 {}
41
makeInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,TestManager & manager)42 static MockEthernetInterface makeInterface(
43 stdplus::PinnedRef<sdbusplus::bus_t> bus, TestManager& manager)
44 {
45 AllIntfInfo info{InterfaceInfo{
46 .type = ARPHRD_ETHER, .idx = 1, .flags = 0, .name = "test0"}};
47 return {bus, manager, info, "/xyz/openbmc_test/network"sv,
48 config::Parser()};
49 }
50
createIPObject(IP::Protocol addressType,const std::string & ipaddress,uint8_t subnetMask)51 auto createIPObject(IP::Protocol addressType, const std::string& ipaddress,
52 uint8_t subnetMask)
53 {
54 return interface.ip(addressType, ipaddress, subnetMask, "");
55 }
56
createStaticGatewayObject(const std::string & gateway,IP::Protocol protocol)57 auto createStaticGatewayObject(const std::string& gateway,
58 IP::Protocol protocol)
59 {
60 return interface.staticGateway(gateway, protocol);
61 }
62
setNtpServers()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
getNtpServers()69 ServerList getNtpServers()
70 {
71 return interface.EthernetInterfaceIntf::ntpServers();
72 }
73 };
74
TEST_F(TestEthernetInterface,Fields)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 stdplus::EtherAddr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
82 constexpr unsigned mtu = 150;
83
84 AllIntfInfo info{InterfaceInfo{
85 .type = ARPHRD_ETHER,
86 .idx = 2,
87 .flags = IFF_RUNNING,
88 .name = "test1",
89 .mac = mac,
90 .mtu = mtu}};
91 MockEthernetInterface intf(bus, manager, info,
92 "/xyz/openbmc_test/network"sv, config::Parser());
93
94 EXPECT_EQ(mtu, intf.mtu());
95 EXPECT_EQ(stdplus::toStr(mac), intf.macAddress());
96 EXPECT_TRUE(intf.linkUp());
97 }
98
TEST_F(TestEthernetInterface,NoIPaddress)99 TEST_F(TestEthernetInterface, NoIPaddress)
100 {
101 EXPECT_TRUE(interface.addrs.empty());
102 }
103
TEST_F(TestEthernetInterface,AddIPAddress)104 TEST_F(TestEthernetInterface, AddIPAddress)
105 {
106 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "127.0.0.1", 16),
107 InvalidArgument);
108 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "127.0.0.1", 32),
109 InvalidArgument);
110 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "192.168.1.1", 0),
111 InvalidArgument);
112 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "::1", 64),
113 InvalidArgument);
114 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "::", 128),
115 InvalidArgument);
116 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "fe80::1", 0),
117 InvalidArgument);
118
119 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
120 EXPECT_THAT(interface.addrs,
121 UnorderedElementsAre(Key("10.10.10.10/16"_sub)));
122 }
123
TEST_F(TestEthernetInterface,AddMultipleAddress)124 TEST_F(TestEthernetInterface, AddMultipleAddress)
125 {
126 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
127 createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
128 EXPECT_THAT(interface.addrs,
129 UnorderedElementsAre(Key("10.10.10.10/16"_sub),
130 Key("20.20.20.20/16"_sub)));
131 }
132
TEST_F(TestEthernetInterface,DeleteIPAddress)133 TEST_F(TestEthernetInterface, DeleteIPAddress)
134 {
135 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
136 createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
137 interface.addrs.at("10.10.10.10/16"_sub)->delete_();
138 EXPECT_THAT(interface.addrs,
139 UnorderedElementsAre(Key("20.20.20.20/16"_sub)));
140 }
141
TEST_F(TestEthernetInterface,CheckObjectPath)142 TEST_F(TestEthernetInterface, CheckObjectPath)
143 {
144 auto path = createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
145 EXPECT_EQ(path.parent_path(), "/xyz/openbmc_test/network/test0");
146 EXPECT_EQ(path.filename(), "10.10.10.10/16");
147 }
148
TEST_F(TestEthernetInterface,addStaticNameServers)149 TEST_F(TestEthernetInterface, addStaticNameServers)
150 {
151 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
152 EXPECT_CALL(manager.mockReload, schedule());
153 interface.staticNameServers(servers);
154 config::Parser parser((confDir / "00-bmc-test0.network").native());
155 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "DNS"));
156 }
157
TEST_F(TestEthernetInterface,getDynamicNameServers)158 TEST_F(TestEthernetInterface, getDynamicNameServers)
159 {
160 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
161 EXPECT_CALL(interface, getNameServerFromResolvd())
162 .WillRepeatedly(testing::Return(servers));
163 EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
164 }
165
TEST_F(TestEthernetInterface,addStaticNTPServers)166 TEST_F(TestEthernetInterface, addStaticNTPServers)
167 {
168 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
169 EXPECT_CALL(manager.mockReload, schedule());
170 interface.staticNTPServers(servers);
171 config::Parser parser((confDir / "00-bmc-test0.network").native());
172 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "NTP"));
173 }
174
TEST_F(TestEthernetInterface,addNTPServers)175 TEST_F(TestEthernetInterface, addNTPServers)
176 {
177 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
178 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
179 EXPECT_THROW(interface.ntpServers(servers), NotAllowed);
180 }
181
TEST_F(TestEthernetInterface,getNTPServers)182 TEST_F(TestEthernetInterface, getNTPServers)
183 {
184 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
185 setNtpServers();
186 EXPECT_EQ(getNtpServers(), servers);
187 }
188
TEST_F(TestEthernetInterface,addGateway)189 TEST_F(TestEthernetInterface, addGateway)
190 {
191 std::string gateway = "10.3.3.3";
192 interface.defaultGateway(gateway);
193 EXPECT_EQ(interface.defaultGateway(), gateway);
194 EXPECT_THROW(interface.defaultGateway6("127.0.0.10"), InvalidArgument);
195 EXPECT_THROW(interface.defaultGateway6("0.0.0.0"), InvalidArgument);
196 EXPECT_THROW(interface.defaultGateway6("224.1.0.0"), InvalidArgument);
197 EXPECT_EQ(interface.defaultGateway(), gateway);
198 interface.defaultGateway("");
199 EXPECT_EQ(interface.defaultGateway(), "");
200 interface.defaultGateway("0.0.0.0");
201 EXPECT_EQ(interface.defaultGateway(), "");
202 }
203
TEST_F(TestEthernetInterface,addGateway6)204 TEST_F(TestEthernetInterface, addGateway6)
205 {
206 std::string gateway6 = "fe80::1";
207 interface.defaultGateway6(gateway6);
208 EXPECT_EQ(interface.defaultGateway6(), gateway6);
209 EXPECT_THROW(interface.defaultGateway6("::1"), InvalidArgument);
210 EXPECT_EQ(interface.defaultGateway6(), gateway6);
211 interface.defaultGateway6("");
212 EXPECT_EQ(interface.defaultGateway6(), "");
213 interface.defaultGateway6("::");
214 EXPECT_EQ(interface.defaultGateway6(), "");
215 }
216
TEST_F(TestEthernetInterface,DHCPEnabled)217 TEST_F(TestEthernetInterface, DHCPEnabled)
218 {
219 EXPECT_CALL(manager.mockReload, schedule())
220 .WillRepeatedly(testing::Return());
221
222 using DHCPConf = EthernetInterfaceIntf::DHCPConf;
223 auto test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
224 EXPECT_EQ(conf, interface.dhcpEnabled());
225 EXPECT_EQ(dhcp4, interface.dhcp4());
226 EXPECT_EQ(dhcp6, interface.dhcp6());
227 EXPECT_EQ(ra, interface.ipv6AcceptRA());
228 };
229 test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
230
231 auto set_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
232 EXPECT_EQ(conf, interface.dhcpEnabled(conf));
233 test(conf, dhcp4, dhcp6, ra);
234 };
235 set_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
236 set_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
237 set_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
238 /*ra=*/true);
239 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
240 set_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
241 /*ra=*/true);
242 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
243
244 auto ind_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
245 EXPECT_EQ(dhcp4, interface.dhcp4(dhcp4));
246 EXPECT_EQ(dhcp6, interface.dhcp6(dhcp6));
247 EXPECT_EQ(ra, interface.ipv6AcceptRA(ra));
248 test(conf, dhcp4, dhcp6, ra);
249 };
250 ind_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
251 ind_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
252 ind_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
253 /*ra=*/true);
254 ind_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/false);
255 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
256 ind_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
257 /*ra=*/true);
258 ind_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/false);
259 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
260 }
261
TEST_F(TestEthernetInterface,AddStaticGateway)262 TEST_F(TestEthernetInterface, AddStaticGateway)
263 {
264 createStaticGatewayObject("10.10.10.1", IP::Protocol::IPv4);
265 EXPECT_THAT(interface.staticGateways,
266 UnorderedElementsAre(Key(std::string("10.10.10.1"))));
267 }
268
TEST_F(TestEthernetInterface,AddMultipleStaticGateways)269 TEST_F(TestEthernetInterface, AddMultipleStaticGateways)
270 {
271 createStaticGatewayObject("10.10.10.1", IP::Protocol::IPv4);
272 createStaticGatewayObject("10.20.30.1", IP::Protocol::IPv4);
273 EXPECT_THAT(interface.staticGateways,
274 UnorderedElementsAre(Key(std::string("10.10.10.1")),
275 Key(std::string("10.20.30.1"))));
276 }
277
TEST_F(TestEthernetInterface,DeleteStaticGateway)278 TEST_F(TestEthernetInterface, DeleteStaticGateway)
279 {
280 createStaticGatewayObject("10.10.10.1", IP::Protocol::IPv4);
281 createStaticGatewayObject("10.20.30.1", IP::Protocol::IPv4);
282
283 interface.staticGateways.at(std::string("10.10.10.1"))->delete_();
284 interface.staticGateways.at(std::string("10.20.30.1"))->delete_();
285 EXPECT_EQ(interface.staticGateways.empty(), true);
286 }
287
TEST_F(TestEthernetInterface,AddIPv6StaticGateway)288 TEST_F(TestEthernetInterface, AddIPv6StaticGateway)
289 {
290 createStaticGatewayObject("2002:903:15f:325::1", IP::Protocol::IPv6);
291 EXPECT_THAT(interface.staticGateways,
292 UnorderedElementsAre(Key(std::string("2002:903:15f:325::1"))));
293 }
294
TEST_F(TestEthernetInterface,AddMultipleIPv6StaticGateways)295 TEST_F(TestEthernetInterface, AddMultipleIPv6StaticGateways)
296 {
297 createStaticGatewayObject("2003:903:15f:325::1", IP::Protocol::IPv6);
298 createStaticGatewayObject("2004:903:15f:325::1", IP::Protocol::IPv6);
299 EXPECT_THAT(interface.staticGateways,
300 UnorderedElementsAre(Key(std::string("2003:903:15f:325::1")),
301 Key(std::string("2004:903:15f:325::1"))));
302 }
303
304 } // namespace network
305 } // namespace phosphor
306