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; 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 42 static MockEthernetInterface 43 makeInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus, 44 TestManager& manager) 45 { 46 AllIntfInfo info{InterfaceInfo{ 47 .type = ARPHRD_ETHER, .idx = 1, .flags = 0, .name = "test0"}}; 48 return {bus, manager, info, "/xyz/openbmc_test/network"sv, 49 config::Parser()}; 50 } 51 52 auto createIPObject(IP::Protocol addressType, const std::string& ipaddress, 53 uint8_t subnetMask) 54 { 55 return interface.ip(addressType, ipaddress, subnetMask, ""); 56 } 57 58 void setNtpServers() 59 { 60 ServerList ntpServers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"}; 61 interface.EthernetInterfaceIntf::ntpServers(ntpServers); 62 } 63 64 ServerList getNtpServers() 65 { 66 return interface.EthernetInterfaceIntf::ntpServers(); 67 } 68 }; 69 70 TEST_F(TestEthernetInterface, Fields) 71 { 72 EXPECT_EQ(0, interface.mtu()); 73 EXPECT_EQ("", interface.macAddress()); 74 EXPECT_FALSE(interface.linkUp()); 75 76 constexpr stdplus::EtherAddr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; 77 constexpr unsigned mtu = 150; 78 79 AllIntfInfo info{InterfaceInfo{.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 93 TEST_F(TestEthernetInterface, NoIPaddress) 94 { 95 EXPECT_TRUE(interface.addrs.empty()); 96 } 97 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 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 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 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 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 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 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 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 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 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 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 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