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
setNtpServers()57 void setNtpServers()
58 {
59 ServerList ntpServers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
60 interface.EthernetInterfaceIntf::ntpServers(ntpServers);
61 }
62
getNtpServers()63 ServerList getNtpServers()
64 {
65 return interface.EthernetInterfaceIntf::ntpServers();
66 }
67 };
68
TEST_F(TestEthernetInterface,Fields)69 TEST_F(TestEthernetInterface, Fields)
70 {
71 EXPECT_EQ(0, interface.mtu());
72 EXPECT_EQ("", interface.macAddress());
73 EXPECT_FALSE(interface.linkUp());
74
75 constexpr stdplus::EtherAddr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
76 constexpr unsigned mtu = 150;
77
78 AllIntfInfo info{InterfaceInfo{
79 .type = ARPHRD_ETHER,
80 .idx = 2,
81 .flags = IFF_RUNNING,
82 .name = "test1",
83 .mac = mac,
84 .mtu = mtu}};
85 MockEthernetInterface intf(bus, manager, info,
86 "/xyz/openbmc_test/network"sv, config::Parser());
87
88 EXPECT_EQ(mtu, intf.mtu());
89 EXPECT_EQ(stdplus::toStr(mac), intf.macAddress());
90 EXPECT_TRUE(intf.linkUp());
91 }
92
TEST_F(TestEthernetInterface,NoIPaddress)93 TEST_F(TestEthernetInterface, NoIPaddress)
94 {
95 EXPECT_TRUE(interface.addrs.empty());
96 }
97
TEST_F(TestEthernetInterface,AddIPAddress)98 TEST_F(TestEthernetInterface, AddIPAddress)
99 {
100 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "127.0.0.1", 16),
101 InvalidArgument);
102 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "127.0.0.1", 32),
103 InvalidArgument);
104 EXPECT_THROW(createIPObject(IP::Protocol::IPv4, "192.168.1.1", 0),
105 InvalidArgument);
106 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "::1", 64),
107 InvalidArgument);
108 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "::", 128),
109 InvalidArgument);
110 EXPECT_THROW(createIPObject(IP::Protocol::IPv6, "fe80::1", 0),
111 InvalidArgument);
112
113 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
114 EXPECT_THAT(interface.addrs,
115 UnorderedElementsAre(Key("10.10.10.10/16"_sub)));
116 }
117
TEST_F(TestEthernetInterface,AddMultipleAddress)118 TEST_F(TestEthernetInterface, AddMultipleAddress)
119 {
120 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
121 createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
122 EXPECT_THAT(interface.addrs,
123 UnorderedElementsAre(Key("10.10.10.10/16"_sub),
124 Key("20.20.20.20/16"_sub)));
125 }
126
TEST_F(TestEthernetInterface,DeleteIPAddress)127 TEST_F(TestEthernetInterface, DeleteIPAddress)
128 {
129 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
130 createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16);
131 interface.addrs.at("10.10.10.10/16"_sub)->delete_();
132 EXPECT_THAT(interface.addrs,
133 UnorderedElementsAre(Key("20.20.20.20/16"_sub)));
134 }
135
TEST_F(TestEthernetInterface,CheckObjectPath)136 TEST_F(TestEthernetInterface, CheckObjectPath)
137 {
138 auto path = createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16);
139 EXPECT_EQ(path.parent_path(), "/xyz/openbmc_test/network/test0");
140 EXPECT_EQ(path.filename(), "10.10.10.10/16");
141 }
142
TEST_F(TestEthernetInterface,addStaticNameServers)143 TEST_F(TestEthernetInterface, addStaticNameServers)
144 {
145 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
146 EXPECT_CALL(manager.mockReload, schedule());
147 interface.staticNameServers(servers);
148 config::Parser parser((confDir / "00-bmc-test0.network").native());
149 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "DNS"));
150 }
151
TEST_F(TestEthernetInterface,getDynamicNameServers)152 TEST_F(TestEthernetInterface, getDynamicNameServers)
153 {
154 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
155 EXPECT_CALL(interface, getNameServerFromResolvd())
156 .WillRepeatedly(testing::Return(servers));
157 EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
158 }
159
TEST_F(TestEthernetInterface,addStaticNTPServers)160 TEST_F(TestEthernetInterface, addStaticNTPServers)
161 {
162 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
163 EXPECT_CALL(manager.mockReload, schedule());
164 interface.staticNTPServers(servers);
165 config::Parser parser((confDir / "00-bmc-test0.network").native());
166 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "NTP"));
167 }
168
TEST_F(TestEthernetInterface,addNTPServers)169 TEST_F(TestEthernetInterface, addNTPServers)
170 {
171 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
172 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
173 EXPECT_THROW(interface.ntpServers(servers), NotAllowed);
174 }
175
TEST_F(TestEthernetInterface,getNTPServers)176 TEST_F(TestEthernetInterface, getNTPServers)
177 {
178 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
179 setNtpServers();
180 EXPECT_EQ(getNtpServers(), servers);
181 }
182
TEST_F(TestEthernetInterface,addGateway)183 TEST_F(TestEthernetInterface, addGateway)
184 {
185 std::string gateway = "10.3.3.3";
186 interface.defaultGateway(gateway);
187 EXPECT_EQ(interface.defaultGateway(), gateway);
188 EXPECT_THROW(interface.defaultGateway6("127.0.0.10"), InvalidArgument);
189 EXPECT_THROW(interface.defaultGateway6("0.0.0.0"), InvalidArgument);
190 EXPECT_THROW(interface.defaultGateway6("224.1.0.0"), InvalidArgument);
191 EXPECT_EQ(interface.defaultGateway(), gateway);
192 interface.defaultGateway("");
193 EXPECT_EQ(interface.defaultGateway(), "");
194 interface.defaultGateway("0.0.0.0");
195 EXPECT_EQ(interface.defaultGateway(), "");
196 }
197
TEST_F(TestEthernetInterface,addGateway6)198 TEST_F(TestEthernetInterface, addGateway6)
199 {
200 std::string gateway6 = "fe80::1";
201 interface.defaultGateway6(gateway6);
202 EXPECT_EQ(interface.defaultGateway6(), gateway6);
203 EXPECT_THROW(interface.defaultGateway6("::1"), InvalidArgument);
204 EXPECT_EQ(interface.defaultGateway6(), gateway6);
205 interface.defaultGateway6("");
206 EXPECT_EQ(interface.defaultGateway6(), "");
207 interface.defaultGateway6("::");
208 EXPECT_EQ(interface.defaultGateway6(), "");
209 }
210
TEST_F(TestEthernetInterface,DHCPEnabled)211 TEST_F(TestEthernetInterface, DHCPEnabled)
212 {
213 EXPECT_CALL(manager.mockReload, schedule())
214 .WillRepeatedly(testing::Return());
215
216 using DHCPConf = EthernetInterfaceIntf::DHCPConf;
217 auto test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
218 EXPECT_EQ(conf, interface.dhcpEnabled());
219 EXPECT_EQ(dhcp4, interface.dhcp4());
220 EXPECT_EQ(dhcp6, interface.dhcp6());
221 EXPECT_EQ(ra, interface.ipv6AcceptRA());
222 };
223 test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
224
225 auto set_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
226 EXPECT_EQ(conf, interface.dhcpEnabled(conf));
227 test(conf, dhcp4, dhcp6, ra);
228 };
229 set_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
230 set_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
231 set_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
232 /*ra=*/true);
233 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
234 set_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
235 /*ra=*/true);
236 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
237
238 auto ind_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) {
239 EXPECT_EQ(dhcp4, interface.dhcp4(dhcp4));
240 EXPECT_EQ(dhcp6, interface.dhcp6(dhcp6));
241 EXPECT_EQ(ra, interface.ipv6AcceptRA(ra));
242 test(conf, dhcp4, dhcp6, ra);
243 };
244 ind_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false);
245 ind_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false);
246 ind_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false,
247 /*ra=*/true);
248 ind_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/false);
249 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true);
250 ind_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false,
251 /*ra=*/true);
252 ind_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/false);
253 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true);
254 }
255
256 } // namespace network
257 } // namespace phosphor
258