1862275aaSWilliam A. Kennington III #include "mock_syscall.hpp"
2c920bdb8SWilliam A. Kennington III #include "netlink.hpp"
3c920bdb8SWilliam A. Kennington III #include "util.hpp"
4c920bdb8SWilliam A. Kennington III 
5c920bdb8SWilliam A. Kennington III #include <linux/netlink.h>
6c920bdb8SWilliam A. Kennington III #include <linux/rtnetlink.h>
7c920bdb8SWilliam A. Kennington III 
889d734b9SPatrick Williams #include <stdplus/raw.hpp>
989d734b9SPatrick Williams 
10c920bdb8SWilliam A. Kennington III #include <cstring>
11*cafc1512SWilliam A. Kennington III #include <format>
12c920bdb8SWilliam A. Kennington III #include <stdexcept>
13c920bdb8SWilliam A. Kennington III #include <string_view>
14c920bdb8SWilliam A. Kennington III 
15c920bdb8SWilliam A. Kennington III #include <gtest/gtest.h>
16c920bdb8SWilliam A. Kennington III 
17c920bdb8SWilliam A. Kennington III namespace phosphor
18c920bdb8SWilliam A. Kennington III {
19c920bdb8SWilliam A. Kennington III namespace network
20c920bdb8SWilliam A. Kennington III {
21c920bdb8SWilliam A. Kennington III namespace netlink
22c920bdb8SWilliam A. Kennington III {
23c920bdb8SWilliam A. Kennington III namespace detail
24c920bdb8SWilliam A. Kennington III {
25c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,TooSmall)26c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, TooSmall)
27c920bdb8SWilliam A. Kennington III {
28c920bdb8SWilliam A. Kennington III     const char buf[] = {'1'};
29c920bdb8SWilliam A. Kennington III     static_assert(sizeof(buf) < sizeof(nlmsghdr));
30c920bdb8SWilliam A. Kennington III     std::string_view data(buf, sizeof(buf));
31c920bdb8SWilliam A. Kennington III 
32c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
33c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
34c920bdb8SWilliam A. Kennington III     bool done = true;
35c920bdb8SWilliam A. Kennington III     EXPECT_THROW(processMsg(data, done, cb), std::runtime_error);
36c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, data.size());
37c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
38c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
39c920bdb8SWilliam A. Kennington III }
40c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,SmallAttrLen)41c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, SmallAttrLen)
42c920bdb8SWilliam A. Kennington III {
43c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
44c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0) - 1;
45c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
46c920bdb8SWilliam A. Kennington III 
47c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
48c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
49c920bdb8SWilliam A. Kennington III     bool done = true;
50c920bdb8SWilliam A. Kennington III     EXPECT_THROW(processMsg(data, done, cb), std::runtime_error);
51c920bdb8SWilliam A. Kennington III     EXPECT_EQ(NLMSG_SPACE(0), data.size());
52c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
53c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
54c920bdb8SWilliam A. Kennington III }
55c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,LargeAttrLen)56c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, LargeAttrLen)
57c920bdb8SWilliam A. Kennington III {
58c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
59c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0) + 1;
60c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
61c920bdb8SWilliam A. Kennington III 
62c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
63c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
64c920bdb8SWilliam A. Kennington III     bool done = true;
65c920bdb8SWilliam A. Kennington III     EXPECT_THROW(processMsg(data, done, cb), std::runtime_error);
66c920bdb8SWilliam A. Kennington III     EXPECT_EQ(NLMSG_SPACE(0), data.size());
67c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
68c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
69c920bdb8SWilliam A. Kennington III }
70c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,NoopMsg)71c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, NoopMsg)
72c920bdb8SWilliam A. Kennington III {
73c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
74c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0);
75c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = NLMSG_NOOP;
76c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
77c920bdb8SWilliam A. Kennington III 
78c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
79c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
80c920bdb8SWilliam A. Kennington III     bool done = true;
81c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
82c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
83c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
84c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
85c920bdb8SWilliam A. Kennington III }
86c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,AckMsg)87c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, AckMsg)
88c920bdb8SWilliam A. Kennington III {
89c920bdb8SWilliam A. Kennington III     nlmsgerr ack{};
90c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
91a19558edSWilliam A. Kennington III     constexpr size_t len = NLMSG_LENGTH(sizeof(ack));
92a19558edSWilliam A. Kennington III     hdr.nlmsg_len = len;
93c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = NLMSG_ERROR;
94a19558edSWilliam A. Kennington III     char buf[NLMSG_ALIGN(len)];
95c920bdb8SWilliam A. Kennington III     std::memcpy(buf, &hdr, sizeof(hdr));
96c920bdb8SWilliam A. Kennington III     std::memcpy(NLMSG_DATA(buf), &ack, sizeof(ack));
97c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&buf), sizeof(buf));
98c920bdb8SWilliam A. Kennington III 
99c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
100c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
101c920bdb8SWilliam A. Kennington III     bool done = true;
102c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
103c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
104c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
105c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
106c920bdb8SWilliam A. Kennington III }
107c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,ErrMsg)108c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, ErrMsg)
109c920bdb8SWilliam A. Kennington III {
110c920bdb8SWilliam A. Kennington III     nlmsgerr err{};
111c920bdb8SWilliam A. Kennington III     err.error = EINVAL;
112c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
113a19558edSWilliam A. Kennington III     constexpr size_t len = NLMSG_LENGTH(sizeof(err));
114a19558edSWilliam A. Kennington III     hdr.nlmsg_len = len;
115c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = NLMSG_ERROR;
116a19558edSWilliam A. Kennington III     char buf[NLMSG_ALIGN(len)];
117c920bdb8SWilliam A. Kennington III     std::memcpy(buf, &hdr, sizeof(hdr));
118c920bdb8SWilliam A. Kennington III     std::memcpy(NLMSG_DATA(buf), &err, sizeof(err));
119c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&buf), sizeof(buf));
120c920bdb8SWilliam A. Kennington III 
121c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
122c920bdb8SWilliam A. Kennington III     nlmsghdr hdrOut;
123c920bdb8SWilliam A. Kennington III     std::string_view dataOut;
124c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr& hdr, std::string_view data) {
125c920bdb8SWilliam A. Kennington III         hdrOut = hdr;
126c920bdb8SWilliam A. Kennington III         dataOut = data;
127c920bdb8SWilliam A. Kennington III         cbCalls++;
128c920bdb8SWilliam A. Kennington III     };
129c920bdb8SWilliam A. Kennington III     bool done = true;
130c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
131c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
132c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
13312beaadaSWilliam A. Kennington III     EXPECT_TRUE(stdplus::raw::equal(hdr, hdrOut));
13412beaadaSWilliam A. Kennington III     EXPECT_TRUE(
13512beaadaSWilliam A. Kennington III         stdplus::raw::equal(err, stdplus::raw::extract<nlmsgerr>(dataOut)));
136c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, dataOut.size());
137c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
138c920bdb8SWilliam A. Kennington III }
139c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,DoneNoMulti)140c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, DoneNoMulti)
141c920bdb8SWilliam A. Kennington III {
142c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
143c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0);
144c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = NLMSG_DONE;
145c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
146c920bdb8SWilliam A. Kennington III 
147c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
148c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
149c920bdb8SWilliam A. Kennington III     bool done = true;
150c920bdb8SWilliam A. Kennington III     EXPECT_THROW(processMsg(data, done, cb), std::runtime_error);
151c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
152c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, cbCalls);
153c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
154c920bdb8SWilliam A. Kennington III }
155c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsg,TwoMultiMsgs)156c920bdb8SWilliam A. Kennington III TEST(ExtractMsg, TwoMultiMsgs)
157c920bdb8SWilliam A. Kennington III {
158c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
159c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0);
160c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = RTM_NEWLINK;
161c920bdb8SWilliam A. Kennington III     hdr.nlmsg_flags = NLM_F_MULTI;
162c920bdb8SWilliam A. Kennington III     std::string buf;
163c920bdb8SWilliam A. Kennington III     buf.append(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
164c920bdb8SWilliam A. Kennington III     buf.append(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
165c920bdb8SWilliam A. Kennington III 
166c920bdb8SWilliam A. Kennington III     std::string_view data = buf;
167c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
168c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
169c920bdb8SWilliam A. Kennington III     bool done = true;
170c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
171c920bdb8SWilliam A. Kennington III     EXPECT_EQ(NLMSG_SPACE(0), data.size());
172c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
173c920bdb8SWilliam A. Kennington III     EXPECT_FALSE(done);
174c920bdb8SWilliam A. Kennington III 
175c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
176c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
177c920bdb8SWilliam A. Kennington III     EXPECT_EQ(2, cbCalls);
178c920bdb8SWilliam A. Kennington III     EXPECT_FALSE(done);
179c920bdb8SWilliam A. Kennington III }
180c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,MultiMsgValid)181c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, MultiMsgValid)
182c920bdb8SWilliam A. Kennington III {
183c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
184c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0);
185c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = RTM_NEWLINK;
186c920bdb8SWilliam A. Kennington III     hdr.nlmsg_flags = NLM_F_MULTI;
187c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
188c920bdb8SWilliam A. Kennington III 
189c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
190c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
191c920bdb8SWilliam A. Kennington III     bool done = true;
192c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
193c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
194c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
195c920bdb8SWilliam A. Kennington III     EXPECT_FALSE(done);
196c920bdb8SWilliam A. Kennington III 
197c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = NLMSG_DONE;
198c920bdb8SWilliam A. Kennington III     hdr.nlmsg_flags = 0;
199c920bdb8SWilliam A. Kennington III     data = std::string_view(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
200c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
201c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
202c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
203c920bdb8SWilliam A. Kennington III     EXPECT_TRUE(done);
204c920bdb8SWilliam A. Kennington III }
205c920bdb8SWilliam A. Kennington III 
TEST(ExtractMsgs,MultiMsgInvalid)206c920bdb8SWilliam A. Kennington III TEST(ExtractMsgs, MultiMsgInvalid)
207c920bdb8SWilliam A. Kennington III {
208c920bdb8SWilliam A. Kennington III     nlmsghdr hdr{};
209c920bdb8SWilliam A. Kennington III     hdr.nlmsg_len = NLMSG_LENGTH(0);
210c920bdb8SWilliam A. Kennington III     hdr.nlmsg_type = RTM_NEWLINK;
211c920bdb8SWilliam A. Kennington III     hdr.nlmsg_flags = NLM_F_MULTI;
212c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
213c920bdb8SWilliam A. Kennington III 
214c920bdb8SWilliam A. Kennington III     size_t cbCalls = 0;
215c920bdb8SWilliam A. Kennington III     auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
216c920bdb8SWilliam A. Kennington III     bool done = true;
217c920bdb8SWilliam A. Kennington III     processMsg(data, done, cb);
218c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
219c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
220c920bdb8SWilliam A. Kennington III     EXPECT_FALSE(done);
221c920bdb8SWilliam A. Kennington III 
222c920bdb8SWilliam A. Kennington III     hdr.nlmsg_flags = 0;
223c920bdb8SWilliam A. Kennington III     data = std::string_view(reinterpret_cast<char*>(&hdr), NLMSG_SPACE(0));
224c920bdb8SWilliam A. Kennington III     EXPECT_THROW(processMsg(data, done, cb), std::runtime_error);
225c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
226c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, cbCalls);
227c920bdb8SWilliam A. Kennington III     EXPECT_FALSE(done);
228c920bdb8SWilliam A. Kennington III }
229c920bdb8SWilliam A. Kennington III 
230c920bdb8SWilliam A. Kennington III } // namespace detail
231c920bdb8SWilliam A. Kennington III 
TEST(ExtractRtAttr,TooSmall)232c920bdb8SWilliam A. Kennington III TEST(ExtractRtAttr, TooSmall)
233c920bdb8SWilliam A. Kennington III {
234c920bdb8SWilliam A. Kennington III     const char buf[] = {'1'};
235c920bdb8SWilliam A. Kennington III     static_assert(sizeof(buf) < sizeof(rtattr));
236c920bdb8SWilliam A. Kennington III     std::string_view data(buf, sizeof(buf));
237c920bdb8SWilliam A. Kennington III 
238c920bdb8SWilliam A. Kennington III     EXPECT_THROW(extractRtAttr(data), std::runtime_error);
239c920bdb8SWilliam A. Kennington III     EXPECT_EQ(1, data.size());
240c920bdb8SWilliam A. Kennington III }
241c920bdb8SWilliam A. Kennington III 
TEST(ExtractRtAttr,SmallAttrLen)242c920bdb8SWilliam A. Kennington III TEST(ExtractRtAttr, SmallAttrLen)
243c920bdb8SWilliam A. Kennington III {
244c920bdb8SWilliam A. Kennington III     rtattr rta{};
245c920bdb8SWilliam A. Kennington III     rta.rta_len = RTA_LENGTH(0) - 1;
246c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&rta), RTA_SPACE(0));
247c920bdb8SWilliam A. Kennington III 
248c920bdb8SWilliam A. Kennington III     EXPECT_THROW(extractRtAttr(data), std::runtime_error);
249c920bdb8SWilliam A. Kennington III     EXPECT_EQ(RTA_SPACE(0), data.size());
250c920bdb8SWilliam A. Kennington III }
251c920bdb8SWilliam A. Kennington III 
TEST(ExtractRtAttr,LargeAttrLen)252c920bdb8SWilliam A. Kennington III TEST(ExtractRtAttr, LargeAttrLen)
253c920bdb8SWilliam A. Kennington III {
254c920bdb8SWilliam A. Kennington III     rtattr rta{};
255c920bdb8SWilliam A. Kennington III     rta.rta_len = RTA_LENGTH(0) + 1;
256c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&rta), RTA_SPACE(0));
257c920bdb8SWilliam A. Kennington III 
258c920bdb8SWilliam A. Kennington III     EXPECT_THROW(extractRtAttr(data), std::runtime_error);
259c920bdb8SWilliam A. Kennington III     EXPECT_EQ(RTA_SPACE(0), data.size());
260c920bdb8SWilliam A. Kennington III }
261c920bdb8SWilliam A. Kennington III 
TEST(ExtractRtAttr,NoData)262c920bdb8SWilliam A. Kennington III TEST(ExtractRtAttr, NoData)
263c920bdb8SWilliam A. Kennington III {
264c920bdb8SWilliam A. Kennington III     rtattr rta{};
265c920bdb8SWilliam A. Kennington III     rta.rta_len = RTA_LENGTH(0);
266c920bdb8SWilliam A. Kennington III     std::string_view data(reinterpret_cast<char*>(&rta), RTA_SPACE(0));
267c920bdb8SWilliam A. Kennington III 
268c920bdb8SWilliam A. Kennington III     auto [hdr, attr] = extractRtAttr(data);
269c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, data.size());
270c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, attr.size());
271c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, std::memcmp(&rta, &hdr, sizeof(rta)));
272c920bdb8SWilliam A. Kennington III }
273c920bdb8SWilliam A. Kennington III 
TEST(ExtractRtAttr,SomeData)274c920bdb8SWilliam A. Kennington III TEST(ExtractRtAttr, SomeData)
275c920bdb8SWilliam A. Kennington III {
276c920bdb8SWilliam A. Kennington III     const char attrbuf[] = "abcd";
277c920bdb8SWilliam A. Kennington III     const char nextbuf[] = "efgh";
278c920bdb8SWilliam A. Kennington III     rtattr rta{};
279c920bdb8SWilliam A. Kennington III     rta.rta_len = RTA_LENGTH(sizeof(attrbuf));
280c920bdb8SWilliam A. Kennington III 
281c920bdb8SWilliam A. Kennington III     char buf[RTA_SPACE(sizeof(attrbuf)) + sizeof(nextbuf)];
282c920bdb8SWilliam A. Kennington III     memcpy(buf, &rta, sizeof(rta));
283c920bdb8SWilliam A. Kennington III     memcpy(RTA_DATA(buf), &attrbuf, sizeof(attrbuf));
284c920bdb8SWilliam A. Kennington III     memcpy(buf + RTA_SPACE(sizeof(attrbuf)), &nextbuf, sizeof(nextbuf));
285c920bdb8SWilliam A. Kennington III     std::string_view data(buf, sizeof(buf));
286c920bdb8SWilliam A. Kennington III 
287c920bdb8SWilliam A. Kennington III     auto [hdr, attr] = extractRtAttr(data);
288c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, memcmp(&rta, &hdr, sizeof(rta)));
289c920bdb8SWilliam A. Kennington III     EXPECT_EQ(sizeof(attrbuf), attr.size());
290c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, memcmp(&attrbuf, attr.data(), sizeof(attrbuf)));
291c920bdb8SWilliam A. Kennington III     EXPECT_EQ(sizeof(nextbuf), data.size());
292c920bdb8SWilliam A. Kennington III     EXPECT_EQ(0, memcmp(&nextbuf, data.data(), sizeof(nextbuf)));
293c920bdb8SWilliam A. Kennington III }
294c920bdb8SWilliam A. Kennington III 
2955bb7da95SWilliam A. Kennington III class PerformRequest : public testing::Test
2965bb7da95SWilliam A. Kennington III {
2975bb7da95SWilliam A. Kennington III   public:
doLinkDump(unsigned ifs)2987784856dSWilliam A. Kennington III     void doLinkDump(unsigned ifs)
2995bb7da95SWilliam A. Kennington III     {
3007784856dSWilliam A. Kennington III         system::mock_clear();
3017784856dSWilliam A. Kennington III         for (unsigned i = 0; i < ifs; ++i)
3025bb7da95SWilliam A. Kennington III         {
3039c441fd4SWilliam A. Kennington III             system::mock_addIF(InterfaceInfo{.type = 1u,
3049c441fd4SWilliam A. Kennington III                                              .idx = i + 1u,
3059c441fd4SWilliam A. Kennington III                                              .flags = 0,
306*cafc1512SWilliam A. Kennington III                                              .name = std::format("eth{}", i)});
3075bb7da95SWilliam A. Kennington III         }
3085bb7da95SWilliam A. Kennington III 
3095bb7da95SWilliam A. Kennington III         size_t cbCalls = 0;
3105bb7da95SWilliam A. Kennington III         auto cb = [&](const nlmsghdr&, std::string_view) { cbCalls++; };
3115bb7da95SWilliam A. Kennington III         ifinfomsg msg{};
3125bb7da95SWilliam A. Kennington III         netlink::performRequest(NETLINK_ROUTE, RTM_GETLINK, NLM_F_DUMP, msg,
3135bb7da95SWilliam A. Kennington III                                 cb);
3145bb7da95SWilliam A. Kennington III         EXPECT_EQ(ifs, cbCalls);
3155bb7da95SWilliam A. Kennington III     }
3165bb7da95SWilliam A. Kennington III };
3175bb7da95SWilliam A. Kennington III 
TEST_F(PerformRequest,NoResponse)3185bb7da95SWilliam A. Kennington III TEST_F(PerformRequest, NoResponse)
3195bb7da95SWilliam A. Kennington III {
3205bb7da95SWilliam A. Kennington III     doLinkDump(0);
3215bb7da95SWilliam A. Kennington III }
3225bb7da95SWilliam A. Kennington III 
TEST_F(PerformRequest,SingleResponse)3235bb7da95SWilliam A. Kennington III TEST_F(PerformRequest, SingleResponse)
3245bb7da95SWilliam A. Kennington III {
3255bb7da95SWilliam A. Kennington III     doLinkDump(1);
3265bb7da95SWilliam A. Kennington III }
3275bb7da95SWilliam A. Kennington III 
TEST_F(PerformRequest,MultiResponse)3285bb7da95SWilliam A. Kennington III TEST_F(PerformRequest, MultiResponse)
3295bb7da95SWilliam A. Kennington III {
3305bb7da95SWilliam A. Kennington III     doLinkDump(3);
3315bb7da95SWilliam A. Kennington III }
3325bb7da95SWilliam A. Kennington III 
TEST_F(PerformRequest,MultiMsg)3335bb7da95SWilliam A. Kennington III TEST_F(PerformRequest, MultiMsg)
3345bb7da95SWilliam A. Kennington III {
3355bb7da95SWilliam A. Kennington III     doLinkDump(1000);
3365bb7da95SWilliam A. Kennington III }
3375bb7da95SWilliam A. Kennington III 
338c920bdb8SWilliam A. Kennington III } // namespace netlink
339c920bdb8SWilliam A. Kennington III } // namespace network
340c920bdb8SWilliam A. Kennington III } // namespace phosphor
341