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 ether_addr 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(std::to_string(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( 100 IfAddr(in_addr{htonl(0x0a0a0a0a)}, 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(Key(IfAddr(in_addr{htonl(0x0a0a0a0a)}, 16)), 110 Key(IfAddr(in_addr{htonl(0x14141414)}, 16)))); 111 } 112 113 TEST_F(TestEthernetInterface, DeleteIPAddress) 114 { 115 createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16); 116 createIPObject(IP::Protocol::IPv4, "20.20.20.20", 16); 117 interface.addrs.at(IfAddr(in_addr{htonl(0x0a0a0a0a)}, 16))->delete_(); 118 EXPECT_THAT(interface.addrs, UnorderedElementsAre(Key( 119 IfAddr(in_addr{htonl(0x14141414)}, 16)))); 120 } 121 122 TEST_F(TestEthernetInterface, CheckObjectPath) 123 { 124 auto path = createIPObject(IP::Protocol::IPv4, "10.10.10.10", 16); 125 EXPECT_EQ(path.parent_path(), "/xyz/openbmc_test/network/test0"); 126 EXPECT_EQ(path.filename(), "10.10.10.10/16"); 127 } 128 129 TEST_F(TestEthernetInterface, addStaticNameServers) 130 { 131 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"}; 132 EXPECT_CALL(manager.mockReload, schedule()); 133 interface.staticNameServers(servers); 134 config::Parser parser((confDir / "00-bmc-test0.network").native()); 135 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "DNS")); 136 } 137 138 TEST_F(TestEthernetInterface, getDynamicNameServers) 139 { 140 ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"}; 141 EXPECT_CALL(interface, getNameServerFromResolvd()) 142 .WillRepeatedly(testing::Return(servers)); 143 EXPECT_EQ(interface.getNameServerFromResolvd(), servers); 144 } 145 146 TEST_F(TestEthernetInterface, addStaticNTPServers) 147 { 148 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"}; 149 EXPECT_CALL(manager.mockReload, schedule()); 150 interface.staticNTPServers(servers); 151 config::Parser parser((confDir / "00-bmc-test0.network").native()); 152 EXPECT_EQ(servers, parser.map.getValueStrings("Network", "NTP")); 153 } 154 155 TEST_F(TestEthernetInterface, addNTPServers) 156 { 157 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 158 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"}; 159 EXPECT_THROW(interface.ntpServers(servers), NotAllowed); 160 } 161 162 TEST_F(TestEthernetInterface, getNTPServers) 163 { 164 ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"}; 165 setNtpServers(); 166 EXPECT_EQ(getNtpServers(), servers); 167 } 168 169 TEST_F(TestEthernetInterface, addGateway) 170 { 171 std::string gateway = "10.3.3.3"; 172 interface.defaultGateway(gateway); 173 EXPECT_EQ(interface.defaultGateway(), gateway); 174 interface.defaultGateway(""); 175 EXPECT_EQ(interface.defaultGateway(), ""); 176 } 177 178 TEST_F(TestEthernetInterface, addGateway6) 179 { 180 std::string gateway6 = "ffff:ffff:ffff:fe80::1"; 181 interface.defaultGateway6(gateway6); 182 EXPECT_EQ(interface.defaultGateway6(), gateway6); 183 interface.defaultGateway6(""); 184 EXPECT_EQ(interface.defaultGateway6(), ""); 185 } 186 187 TEST_F(TestEthernetInterface, DHCPEnabled) 188 { 189 EXPECT_CALL(manager.mockReload, schedule()) 190 .WillRepeatedly(testing::Return()); 191 192 using DHCPConf = EthernetInterfaceIntf::DHCPConf; 193 auto test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) { 194 EXPECT_EQ(conf, interface.dhcpEnabled()); 195 EXPECT_EQ(dhcp4, interface.dhcp4()); 196 EXPECT_EQ(dhcp6, interface.dhcp6()); 197 EXPECT_EQ(ra, interface.ipv6AcceptRA()); 198 }; 199 test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true); 200 201 auto set_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) { 202 EXPECT_EQ(conf, interface.dhcpEnabled(conf)); 203 test(conf, dhcp4, dhcp6, ra); 204 }; 205 set_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false); 206 set_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false); 207 set_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false, 208 /*ra=*/true); 209 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true); 210 set_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false, 211 /*ra=*/true); 212 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true); 213 214 auto ind_test = [&](DHCPConf conf, bool dhcp4, bool dhcp6, bool ra) { 215 EXPECT_EQ(dhcp4, interface.dhcp4(dhcp4)); 216 EXPECT_EQ(dhcp6, interface.dhcp6(dhcp6)); 217 EXPECT_EQ(ra, interface.ipv6AcceptRA(ra)); 218 test(conf, dhcp4, dhcp6, ra); 219 }; 220 ind_test(DHCPConf::none, /*dhcp4=*/false, /*dhcp6=*/false, /*ra=*/false); 221 ind_test(DHCPConf::v4, /*dhcp4=*/true, /*dhcp6=*/false, /*ra=*/false); 222 ind_test(DHCPConf::v6stateless, /*dhcp4=*/false, /*dhcp6=*/false, 223 /*ra=*/true); 224 ind_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/false); 225 set_test(DHCPConf::v6, /*dhcp4=*/false, /*dhcp6=*/true, /*ra=*/true); 226 ind_test(DHCPConf::v4v6stateless, /*dhcp4=*/true, /*dhcp6=*/false, 227 /*ra=*/true); 228 ind_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/false); 229 set_test(DHCPConf::both, /*dhcp4=*/true, /*dhcp6=*/true, /*ra=*/true); 230 } 231 232 } // namespace network 233 } // namespace phosphor 234