blob: a8cfbb2553c1a33543b231f30c4fcf44b60784bb [file] [log] [blame]
Patrick Venture189d44e2018-07-09 12:30:59 -07001#include "ncsi_util.hpp"
2
Ratan Guptabbe45792018-03-23 00:22:55 +05303#include <linux/ncsi.h>
Ratan Guptabbe45792018-03-23 00:22:55 +05304#include <netlink/genl/ctrl.h>
Gunnar Mills57d9c502018-09-14 14:42:34 -05005#include <netlink/genl/genl.h>
6#include <netlink/netlink.h>
Ratan Guptabbe45792018-03-23 00:22:55 +05307
Patrick Williams89d734b2023-05-10 07:50:25 -05008#include <phosphor-logging/lg2.hpp>
William A. Kennington IIIcbe50732023-07-25 13:52:18 -07009#include <stdplus/numeric/str.hpp>
10#include <stdplus/str/buf.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050011
Jiaqing Zhao7c44a782022-04-10 15:30:04 +080012#include <vector>
Ratan Guptabbe45792018-03-23 00:22:55 +053013
14namespace phosphor
15{
16namespace network
17{
18namespace ncsi
19{
20
Gunnar Mills57d9c502018-09-14 14:42:34 -050021using CallBack = int (*)(struct nl_msg* msg, void* arg);
Ratan Guptaaac603e2018-03-23 00:25:54 +053022
William A. Kennington IIIcbe50732023-07-25 13:52:18 -070023static stdplus::StrBuf toHexStr(std::span<const uint8_t> c) noexcept
24{
25 stdplus::StrBuf ret;
26 if (c.empty())
27 {
28 return ret;
29 }
30 stdplus::IntToStr<16, uint8_t> its;
Johnathan Mantey1ebea282024-02-15 10:26:06 -080031 auto oit = ret.append(c.size() * 3);
William A. Kennington IIIcbe50732023-07-25 13:52:18 -070032 auto cit = c.begin();
33 oit = its(oit, *cit++, 2);
34 for (; cit != c.end(); ++cit)
35 {
36 *oit++ = ' ';
37 oit = its(oit, *cit, 2);
38 }
Johnathan Mantey1ebea282024-02-15 10:26:06 -080039 *oit = 0;
William A. Kennington IIIcbe50732023-07-25 13:52:18 -070040 return ret;
41}
42
Ratan Guptaaac603e2018-03-23 00:25:54 +053043namespace internal
44{
Ratan Guptabbe45792018-03-23 00:22:55 +053045
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050046struct NCSIPacketHeader
47{
48 uint8_t MCID;
49 uint8_t revision;
50 uint8_t reserved;
51 uint8_t id;
52 uint8_t type;
53 uint8_t channel;
54 uint16_t length;
55 uint32_t rsvd[2];
56};
57
58class Command
59{
60 public:
61 Command() = delete;
62 ~Command() = default;
63 Command(const Command&) = delete;
64 Command& operator=(const Command&) = delete;
65 Command(Command&&) = default;
66 Command& operator=(Command&&) = default;
67 Command(
Johnathan Mantey1ebea282024-02-15 10:26:06 -080068 int ncsiCmd, int operation = DEFAULT_VALUE,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050069 std::span<const unsigned char> p = std::span<const unsigned char>()) :
Patrick Williamsad205022024-08-16 15:20:07 -040070 ncsi_cmd(ncsiCmd), operation(operation), payload(p)
Patrick Williams89d734b2023-05-10 07:50:25 -050071 {}
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050072
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050073 int ncsi_cmd;
Johnathan Mantey1ebea282024-02-15 10:26:06 -080074 int operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050075 std::span<const unsigned char> payload;
76};
77
Ratan Guptabbe45792018-03-23 00:22:55 +053078using nlMsgPtr = std::unique_ptr<nl_msg, decltype(&::nlmsg_free)>;
79using nlSocketPtr = std::unique_ptr<nl_sock, decltype(&::nl_socket_free)>;
80
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050081CallBack infoCallBack = [](struct nl_msg* msg, void* arg) {
Ratan Guptaaac603e2018-03-23 00:25:54 +053082 using namespace phosphor::network::ncsi;
83 auto nlh = nlmsg_hdr(msg);
84
Gunnar Mills57d9c502018-09-14 14:42:34 -050085 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
86 struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070087 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
88 {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +053089 };
90
Gunnar Mills57d9c502018-09-14 14:42:34 -050091 struct nlattr* packagetb[NCSI_PKG_ATTR_MAX + 1] = {nullptr};
92 struct nla_policy packagePolicy[NCSI_PKG_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070093 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
94 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +053095 };
96
Gunnar Mills57d9c502018-09-14 14:42:34 -050097 struct nlattr* channeltb[NCSI_CHANNEL_ATTR_MAX + 1] = {nullptr};
98 struct nla_policy channelPolicy[NCSI_CHANNEL_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070099 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
100 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_UNSPEC, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +0530101 };
102
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500103 *(int*)arg = 0;
104
Ratan Guptaaac603e2018-03-23 00:25:54 +0530105 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
106 if (!tb[NCSI_ATTR_PACKAGE_LIST])
107 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700108 lg2::error("No Packages");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530109 return -1;
110 }
111
112 auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
113 if (!attrTgt)
114 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700115 lg2::error("Package list attribute is null");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530116 return -1;
117 }
118
119 auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
120 nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
121 {
122 ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
123 packagePolicy);
124 if (ret < 0)
125 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700126 lg2::error("Failed to parse package nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530127 return -1;
128 }
129
130 if (packagetb[NCSI_PKG_ATTR_ID])
131 {
132 auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700133 lg2::debug("Package has id : {ATTR_ID}", "ATTR_ID", lg2::hex,
134 attrID);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530135 }
136 else
137 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700138 lg2::debug("Package with no id");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530139 }
140
141 if (packagetb[NCSI_PKG_ATTR_FORCED])
142 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700143 lg2::debug("This package is forced");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530144 }
145
146 auto channelListTarget = static_cast<nlattr*>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500147 nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
Ratan Guptaaac603e2018-03-23 00:25:54 +0530148
149 auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
150 nla_for_each_nested(channelListTarget,
151 packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
152 {
153 ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
154 channelListTarget, channelPolicy);
155 if (ret < 0)
156 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700157 lg2::error("Failed to parse channel nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530158 return -1;
159 }
160
161 if (channeltb[NCSI_CHANNEL_ATTR_ID])
162 {
163 auto channel = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
164 if (channeltb[NCSI_CHANNEL_ATTR_ACTIVE])
165 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700166 lg2::debug("Channel Active : {CHANNEL}", "CHANNEL",
167 lg2::hex, channel);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530168 }
169 else
170 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700171 lg2::debug("Channel Not Active : {CHANNEL}", "CHANNEL",
172 lg2::hex, channel);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530173 }
174
175 if (channeltb[NCSI_CHANNEL_ATTR_FORCED])
176 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700177 lg2::debug("Channel is forced");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530178 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530179 }
180 else
181 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700182 lg2::debug("Channel with no ID");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530183 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530184
Ratan Guptaaac603e2018-03-23 00:25:54 +0530185 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
186 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500187 auto major =
188 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700189 lg2::debug("Channel Major Version : {CHANNEL_MAJOR_VERSION}",
190 "CHANNEL_MAJOR_VERSION", lg2::hex, major);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530191 }
192 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
193 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500194 auto minor =
195 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700196 lg2::debug("Channel Minor Version : {CHANNEL_MINOR_VERSION}",
197 "CHANNEL_MINOR_VERSION", lg2::hex, minor);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530198 }
199 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
200 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500201 auto str =
202 nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700203 lg2::debug("Channel Version Str : {CHANNEL_VERSION_STR}",
204 "CHANNEL_VERSION_STR", str);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530205 }
206 if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
207 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500208 auto link =
209 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700210 lg2::debug("Channel Link State : {LINK_STATE}", "LINK_STATE",
211 lg2::hex, link);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530212 }
213 if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
214 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700215 lg2::debug("Active Vlan ids");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530216 auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
217 auto vid = static_cast<nlattr*>(nla_data(vids));
218 auto len = nla_len(vids);
219 while (nla_ok(vid, len))
220 {
221 auto id = nla_get_u16(vid);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700222 lg2::debug("VID : {VLAN_ID}", "VLAN_ID", id);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530223 vid = nla_next(vid, &len);
224 }
225 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530226 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530227 }
228 return (int)NL_SKIP;
229};
230
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500231CallBack sendCallBack = [](struct nl_msg* msg, void* arg) {
232 using namespace phosphor::network::ncsi;
233 auto nlh = nlmsg_hdr(msg);
234 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
235 static struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
236 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
237 {NLA_U32, 0, 0}, {NLA_U32, 0, 0}, {NLA_BINARY, 0, 0},
238 {NLA_FLAG, 0, 0}, {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
239 };
240
241 *(int*)arg = 0;
242
243 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
244 if (ret)
245 {
Jeremy Kerrde8d6662024-08-01 11:33:52 +0800246 lg2::error("Failed to parse message");
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500247 return ret;
248 }
249
Jian Zhang442d9e52022-10-20 22:11:14 +0800250 if (tb[NCSI_ATTR_DATA] == nullptr)
251 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700252 lg2::error("Response: No data");
Jian Zhang442d9e52022-10-20 22:11:14 +0800253 return -1;
254 }
255
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500256 auto data_len = nla_len(tb[NCSI_ATTR_DATA]) - sizeof(NCSIPacketHeader);
Patrick Williamsad205022024-08-16 15:20:07 -0400257 unsigned char* data =
258 (unsigned char*)nla_data(tb[NCSI_ATTR_DATA]) + sizeof(NCSIPacketHeader);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500259
260 // Dump the response to stdout. Enhancement: option to save response data
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700261 auto str = toHexStr(std::span<const unsigned char>(data, data_len));
262 lg2::debug("Response {DATA_LEN} bytes: {DATA}", "DATA_LEN", data_len,
263 "DATA", str);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500264
265 return 0;
266};
267
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800268int applyCmd(Interface& interface, const Command& cmd,
269 int package = DEFAULT_VALUE, int channel = DEFAULT_VALUE,
270 int flags = NONE, CallBack function = nullptr)
Ratan Guptabbe45792018-03-23 00:22:55 +0530271{
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500272 int cb_ret = 0;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500273 nlSocketPtr socket(nl_socket_alloc(), &::nl_socket_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700274 if (socket == nullptr)
275 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700276 lg2::error("Unable to allocate memory for the socket");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700277 return -ENOMEM;
278 }
279
Ratan Guptabbe45792018-03-23 00:22:55 +0530280 auto ret = genl_connect(socket.get());
281 if (ret < 0)
282 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700283 lg2::error("Failed to open the socket , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530284 return ret;
285 }
286
287 auto driverID = genl_ctrl_resolve(socket.get(), "NCSI");
288 if (driverID < 0)
289 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700290 lg2::error("Failed to resolve, RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530291 return driverID;
292 }
293
294 nlMsgPtr msg(nlmsg_alloc(), &::nlmsg_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700295 if (msg == nullptr)
296 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700297 lg2::error("Unable to allocate memory for the message");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700298 return -ENOMEM;
299 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530300
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800301 auto msgHdr = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, driverID, 0,
302 flags, cmd.ncsi_cmd, 0);
Ratan Guptabbe45792018-03-23 00:22:55 +0530303 if (!msgHdr)
304 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700305 lg2::error("Unable to add the netlink headers , COMMAND : {COMMAND}",
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800306 "COMMAND", cmd.ncsi_cmd);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700307 return -ENOMEM;
Ratan Guptabbe45792018-03-23 00:22:55 +0530308 }
309
310 if (package != DEFAULT_VALUE)
311 {
312 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_PACKAGE_ID,
313 package);
314 if (ret < 0)
315 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700316 lg2::error("Failed to set the attribute , RC : {RC} PACKAGE "
317 "{PACKAGE}",
318 "RC", ret, "PACKAGE", lg2::hex, package);
Ratan Guptabbe45792018-03-23 00:22:55 +0530319 return ret;
320 }
321 }
322
323 if (channel != DEFAULT_VALUE)
324 {
325 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_CHANNEL_ID,
326 channel);
327 if (ret < 0)
328 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700329 lg2::error("Failed to set the attribute , RC : {RC} CHANNEL : "
330 "{CHANNEL}",
331 "RC", ret, "CHANNEL", lg2::hex, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530332 return ret;
333 }
334 }
335
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800336 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX,
337 interface.ifindex);
Ratan Guptabbe45792018-03-23 00:22:55 +0530338 if (ret < 0)
339 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700340 lg2::error("Failed to set the attribute , RC : {RC} INTERFACE : "
341 "{INTERFACE}",
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800342 "RC", ret, "INTERFACE", interface);
Ratan Guptabbe45792018-03-23 00:22:55 +0530343 return ret;
344 }
345
Johnathan Mantey5a456062024-02-15 08:45:08 -0800346 if ((cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK) ||
347 (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK))
348 {
349 if (cmd.payload.size() != sizeof(unsigned int))
350 {
351 lg2::error("Package/Channel mask must be 32-bits");
352 return -EINVAL;
353 }
354 int maskAttr =
355 cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK
356 ? NCSI_ATTR_PACKAGE_MASK
357 : NCSI_ATTR_CHANNEL_MASK;
358 ret = nla_put_u32(
359 msg.get(), maskAttr,
360 *(reinterpret_cast<const unsigned int*>(cmd.payload.data())));
361 if (ret < 0)
362 {
363 lg2::error("Failed to set the mask attribute, RC : {RC}", "RC",
364 ret);
365 return ret;
366 }
367 }
368 else if (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SEND_CMD)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500369 {
Patrick Williamsad205022024-08-16 15:20:07 -0400370 std::vector<unsigned char> pl(
371 sizeof(NCSIPacketHeader) + cmd.payload.size());
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500372 NCSIPacketHeader* hdr = (NCSIPacketHeader*)pl.data();
373
374 std::copy(cmd.payload.begin(), cmd.payload.end(),
375 pl.begin() + sizeof(NCSIPacketHeader));
376
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800377 hdr->type = cmd.operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500378 hdr->length = htons(cmd.payload.size());
379
380 ret = nla_put(msg.get(), ncsi_nl_attrs::NCSI_ATTR_DATA, pl.size(),
381 pl.data());
382 if (ret < 0)
383 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700384 lg2::error("Failed to set the data attribute, RC : {RC}", "RC",
385 ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500386 return ret;
387 }
388
389 nl_socket_disable_seq_check(socket.get());
390 }
391
Ratan Guptaaac603e2018-03-23 00:25:54 +0530392 if (function)
393 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500394 cb_ret = 1;
395
Ratan Guptaaac603e2018-03-23 00:25:54 +0530396 // Add a callback function to the socket
Gunnar Mills57d9c502018-09-14 14:42:34 -0500397 nl_socket_modify_cb(socket.get(), NL_CB_VALID, NL_CB_CUSTOM, function,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500398 &cb_ret);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530399 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530400
401 ret = nl_send_auto(socket.get(), msg.get());
402 if (ret < 0)
403 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700404 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530405 return ret;
406 }
407
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500408 do
Ratan Guptabbe45792018-03-23 00:22:55 +0530409 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500410 ret = nl_recvmsgs_default(socket.get());
411 if (ret < 0)
412 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700413 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500414 break;
415 }
416 } while (cb_ret);
417
Ratan Guptabbe45792018-03-23 00:22:55 +0530418 return ret;
419}
420
Gunnar Mills57d9c502018-09-14 14:42:34 -0500421} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530422
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800423std::string to_string(Interface& interface)
424{
425 return std::to_string(interface.ifindex);
426}
427
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800428int Interface::sendOemCommand(int package, int channel, int operation,
429 std::span<const unsigned char> payload)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500430{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700431 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800432 "INTERFACE: {INTERFACE}",
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700433 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800434 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500435 if (!payload.empty())
436 {
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700437 lg2::debug("Payload: {PAYLOAD}", "PAYLOAD", toHexStr(payload));
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500438 }
439
440 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800441 *this,
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800442 internal::Command(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
443 payload),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500444 package, channel, NONE, internal::sendCallBack);
445}
446
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800447int Interface::setChannel(int package, int channel)
Ratan Guptabbe45792018-03-23 00:22:55 +0530448{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800449 lg2::debug("Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE : "
450 "{INTERFACE}",
451 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800452 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500453 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800454 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500455 package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530456}
457
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800458int Interface::clearInterface()
Ratan Guptabbe45792018-03-23 00:22:55 +0530459{
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800460 lg2::debug("ClearInterface , INTERFACE : {INTERFACE}", "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500461 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800462 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE));
Ratan Guptabbe45792018-03-23 00:22:55 +0530463}
464
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800465int Interface::getInfo(int package)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530466{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800467 lg2::debug("Get Info , PACKAGE : {PACKAGE}, INTERFACE: {INTERFACE}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800468 "PACKAGE", lg2::hex, package, "INTERFACE", this);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530469 if (package == DEFAULT_VALUE)
470 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500471 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800472 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_PKG_INFO),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500473 package, DEFAULT_VALUE, NLM_F_DUMP, internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530474 }
475 else
476 {
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800477 return internal::applyCmd(*this, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
478 package, DEFAULT_VALUE, NONE,
479 internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530480 }
481}
482
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800483int Interface::setPackageMask(unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800484{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800485 lg2::debug("Set Package Mask , INTERFACE: {INTERFACE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800486 "INTERFACE", this, "MASK", lg2::hex, mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800487 auto payload = std::span<const unsigned char>(
488 reinterpret_cast<const unsigned char*>(&mask),
489 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
490 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800491 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK, 0,
492 payload));
Johnathan Mantey5a456062024-02-15 08:45:08 -0800493}
494
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800495int Interface::setChannelMask(int package, unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800496{
497 lg2::debug(
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800498 "Set Channel Mask , INTERFACE: {INTERFACE}, PACKAGE : {PACKAGE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800499 "INTERFACE", this, "PACKAGE", lg2::hex, package, "MASK", lg2::hex,
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800500 mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800501 auto payload = std::span<const unsigned char>(
502 reinterpret_cast<const unsigned char*>(&mask),
503 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
504 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800505 *this,
Johnathan Mantey5a456062024-02-15 08:45:08 -0800506 internal::Command(ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK, 0,
507 payload),
508 package);
509 return 0;
510}
511
Gunnar Mills57d9c502018-09-14 14:42:34 -0500512} // namespace ncsi
513} // namespace network
514} // namespace phosphor