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