1 #include "config_parser.hpp"
2 #include "ipaddress.hpp"
3 #include "mock_network_manager.hpp"
4 #include "mock_syscall.hpp"
5 #include "util.hpp"
6 
7 #include <arpa/inet.h>
8 #include <net/if.h>
9 #include <netinet/in.h>
10 #include <stdlib.h>
11 
12 #include <exception>
13 #include <fstream>
14 #include <sdbusplus/bus.hpp>
15 #include <xyz/openbmc_project/Common/error.hpp>
16 
17 #include <gtest/gtest.h>
18 
19 namespace phosphor
20 {
21 namespace network
22 {
23 
24 class TestEthernetInterface : public testing::Test
25 {
26   public:
27     sdbusplus::bus::bus bus;
28     MockManager manager;
29     MockEthernetInterface interface;
30     std::string confDir;
31     TestEthernetInterface() :
32         bus(sdbusplus::bus::new_default()),
33         manager(bus, "/xyz/openbmc_test/network", "/tmp/"),
34         interface(makeInterface(bus, manager))
35 
36     {
37         setConfDir();
38     }
39 
40     void setConfDir()
41     {
42         char tmp[] = "/tmp/EthernetInterface.XXXXXX";
43         confDir = mkdtemp(tmp);
44         manager.setConfDir(confDir);
45     }
46 
47     ~TestEthernetInterface()
48     {
49         if (confDir != "")
50         {
51             fs::remove_all(confDir);
52         }
53     }
54 
55     static constexpr ether_addr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
56 
57     static MockEthernetInterface makeInterface(sdbusplus::bus::bus& bus,
58                                                MockManager& manager)
59     {
60         mock_clear();
61         mock_addIF("test0", 1, mac);
62         return {bus, "/xyz/openbmc_test/network/test0",
63                 EthernetInterface::DHCPConf::none, manager, true};
64     }
65 
66     int countIPObjects()
67     {
68         return interface.getAddresses().size();
69     }
70 
71     bool isIPObjectExist(const std::string& ipaddress)
72     {
73         auto address = interface.getAddresses().find(ipaddress);
74         if (address == interface.getAddresses().end())
75         {
76             return false;
77         }
78         return true;
79     }
80 
81     bool deleteIPObject(const std::string& ipaddress)
82     {
83         auto address = interface.getAddresses().find(ipaddress);
84         if (address == interface.getAddresses().end())
85         {
86             return false;
87         }
88         address->second->delete_();
89         return true;
90     }
91 
92     std::string getObjectPath(const std::string& ipaddress, uint8_t subnetMask,
93                               const std::string& gateway)
94     {
95         IP::Protocol addressType = IP::Protocol::IPv4;
96 
97         return interface.generateObjectPath(addressType, ipaddress, subnetMask,
98                                             gateway);
99     }
100 
101     void createIPObject(IP::Protocol addressType, const std::string& ipaddress,
102                         uint8_t subnetMask, const std::string& gateway)
103     {
104         interface.ip(addressType, ipaddress, subnetMask, gateway);
105     }
106 };
107 
108 TEST_F(TestEthernetInterface, NoIPaddress)
109 {
110     EXPECT_EQ(countIPObjects(), 0);
111     EXPECT_EQ(mac_address::toString(mac), interface.macAddress());
112 }
113 
114 TEST_F(TestEthernetInterface, AddIPAddress)
115 {
116     IP::Protocol addressType = IP::Protocol::IPv4;
117     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
118     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
119 }
120 
121 TEST_F(TestEthernetInterface, AddMultipleAddress)
122 {
123     IP::Protocol addressType = IP::Protocol::IPv4;
124     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
125     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
126     EXPECT_EQ(true, isIPObjectExist("10.10.10.10"));
127     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
128 }
129 
130 TEST_F(TestEthernetInterface, DeleteIPAddress)
131 {
132     IP::Protocol addressType = IP::Protocol::IPv4;
133     createIPObject(addressType, "10.10.10.10", 16, "10.10.10.1");
134     createIPObject(addressType, "20.20.20.20", 16, "20.20.20.1");
135     deleteIPObject("10.10.10.10");
136     EXPECT_EQ(false, isIPObjectExist("10.10.10.10"));
137     EXPECT_EQ(true, isIPObjectExist("20.20.20.20"));
138 }
139 
140 TEST_F(TestEthernetInterface, DeleteInvalidIPAddress)
141 {
142     EXPECT_EQ(false, deleteIPObject("10.10.10.10"));
143 }
144 
145 TEST_F(TestEthernetInterface, CheckObjectPath)
146 {
147     std::string ipaddress = "10.10.10.10";
148     uint8_t prefix = 16;
149     std::string gateway = "10.10.10.1";
150 
151     std::string expectedObjectPath = "/xyz/openbmc_test/network/test0/ipv4/";
152     std::stringstream hexId;
153 
154     std::string hashString = ipaddress;
155     hashString += std::to_string(prefix);
156     hashString += gateway;
157 
158     hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
159     expectedObjectPath += hexId.str();
160 
161     EXPECT_EQ(expectedObjectPath, getObjectPath(ipaddress, prefix, gateway));
162 }
163 
164 TEST_F(TestEthernetInterface, addStaticNameServers)
165 {
166     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
167     EXPECT_CALL(manager, restartSystemdUnit(networkdService)).Times(1);
168     interface.staticNameServers(servers);
169     fs::path filePath = confDir;
170     filePath /= "00-bmc-test0.network";
171     config::Parser parser(filePath.string());
172     config::ReturnCode rc = config::ReturnCode::SUCCESS;
173     config::ValueList values;
174     std::tie(rc, values) = parser.getValues("Network", "DNS");
175     EXPECT_EQ(servers, values);
176 }
177 
178 TEST_F(TestEthernetInterface, addDynamicNameServers)
179 {
180     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
181     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
182     EXPECT_THROW(interface.nameservers(servers), NotAllowed);
183 }
184 
185 TEST_F(TestEthernetInterface, getDynamicNameServers)
186 {
187     ServerList servers = {"9.1.1.1", "9.2.2.2", "9.3.3.3"};
188     EXPECT_CALL(interface, getNameServerFromResolvd())
189         .WillRepeatedly(testing::Return(servers));
190     EXPECT_EQ(interface.getNameServerFromResolvd(), servers);
191 }
192 
193 TEST_F(TestEthernetInterface, addNTPServers)
194 {
195     ServerList servers = {"10.1.1.1", "10.2.2.2", "10.3.3.3"};
196     EXPECT_CALL(manager, restartSystemdUnit(networkdService)).Times(1);
197     interface.ntpServers(servers);
198     fs::path filePath = confDir;
199     filePath /= "00-bmc-test0.network";
200     config::Parser parser(filePath.string());
201     config::ReturnCode rc = config::ReturnCode::SUCCESS;
202     config::ValueList values;
203     std::tie(rc, values) = parser.getValues("Network", "NTP");
204     EXPECT_EQ(servers, values);
205 }
206 
207 TEST_F(TestEthernetInterface, addGateway)
208 {
209     std::string gateway = "10.3.3.3";
210     interface.defaultGateway(gateway);
211     EXPECT_EQ(interface.defaultGateway(), gateway);
212 }
213 
214 TEST_F(TestEthernetInterface, addGateway6)
215 {
216     std::string gateway6 = "ffff:ffff:ffff:fe80::1";
217     interface.defaultGateway6(gateway6);
218     EXPECT_EQ(interface.defaultGateway6(), gateway6);
219 }
220 
221 } // namespace network
222 } // namespace phosphor
223