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