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