blob: c3d3794c42e327ab4e18bc4aada767fcc414f517 [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 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700246 lg2::error("Failed to parse package");
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
268int applyCmd(int ifindex, const Command& cmd, int package = DEFAULT_VALUE,
Ratan Guptaaac603e2018-03-23 00:25:54 +0530269 int channel = DEFAULT_VALUE, int flags = NONE,
270 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
336 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX, ifindex);
337 if (ret < 0)
338 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700339 lg2::error("Failed to set the attribute , RC : {RC} INTERFACE : "
340 "{INTERFACE}",
341 "RC", ret, "INTERFACE", lg2::hex, ifindex);
Ratan Guptabbe45792018-03-23 00:22:55 +0530342 return ret;
343 }
344
Johnathan Mantey5a456062024-02-15 08:45:08 -0800345 if ((cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK) ||
346 (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK))
347 {
348 if (cmd.payload.size() != sizeof(unsigned int))
349 {
350 lg2::error("Package/Channel mask must be 32-bits");
351 return -EINVAL;
352 }
353 int maskAttr =
354 cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK
355 ? NCSI_ATTR_PACKAGE_MASK
356 : NCSI_ATTR_CHANNEL_MASK;
357 ret = nla_put_u32(
358 msg.get(), maskAttr,
359 *(reinterpret_cast<const unsigned int*>(cmd.payload.data())));
360 if (ret < 0)
361 {
362 lg2::error("Failed to set the mask attribute, RC : {RC}", "RC",
363 ret);
364 return ret;
365 }
366 }
367 else if (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SEND_CMD)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500368 {
Patrick Williamsad205022024-08-16 15:20:07 -0400369 std::vector<unsigned char> pl(
370 sizeof(NCSIPacketHeader) + cmd.payload.size());
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500371 NCSIPacketHeader* hdr = (NCSIPacketHeader*)pl.data();
372
373 std::copy(cmd.payload.begin(), cmd.payload.end(),
374 pl.begin() + sizeof(NCSIPacketHeader));
375
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800376 hdr->type = cmd.operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500377 hdr->length = htons(cmd.payload.size());
378
379 ret = nla_put(msg.get(), ncsi_nl_attrs::NCSI_ATTR_DATA, pl.size(),
380 pl.data());
381 if (ret < 0)
382 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700383 lg2::error("Failed to set the data attribute, RC : {RC}", "RC",
384 ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500385 return ret;
386 }
387
388 nl_socket_disable_seq_check(socket.get());
389 }
390
Ratan Guptaaac603e2018-03-23 00:25:54 +0530391 if (function)
392 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500393 cb_ret = 1;
394
Ratan Guptaaac603e2018-03-23 00:25:54 +0530395 // Add a callback function to the socket
Gunnar Mills57d9c502018-09-14 14:42:34 -0500396 nl_socket_modify_cb(socket.get(), NL_CB_VALID, NL_CB_CUSTOM, function,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500397 &cb_ret);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530398 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530399
400 ret = nl_send_auto(socket.get(), msg.get());
401 if (ret < 0)
402 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700403 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530404 return ret;
405 }
406
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500407 do
Ratan Guptabbe45792018-03-23 00:22:55 +0530408 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500409 ret = nl_recvmsgs_default(socket.get());
410 if (ret < 0)
411 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700412 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500413 break;
414 }
415 } while (cb_ret);
416
Ratan Guptabbe45792018-03-23 00:22:55 +0530417 return ret;
418}
419
Gunnar Mills57d9c502018-09-14 14:42:34 -0500420} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530421
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800422int sendOemCommand(int ifindex, int package, int channel, int operation,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500423 std::span<const unsigned char> payload)
424{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700425 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
426 "INTERFACE_INDEX: {INTERFACE_INDEX}",
427 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
428 "INTERFACE_INDEX", lg2::hex, ifindex);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500429 if (!payload.empty())
430 {
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700431 lg2::debug("Payload: {PAYLOAD}", "PAYLOAD", toHexStr(payload));
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500432 }
433
434 return internal::applyCmd(
435 ifindex,
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800436 internal::Command(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
437 payload),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500438 package, channel, NONE, internal::sendCallBack);
439}
440
Ratan Guptabbe45792018-03-23 00:22:55 +0530441int setChannel(int ifindex, int package, int channel)
442{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700443 lg2::debug(
444 "Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE_INDEX: "
445 "{INTERFACE_INDEX}",
446 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
447 "INTERFACE_INDEX", lg2::hex, ifindex);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500448 return internal::applyCmd(
449 ifindex, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE),
450 package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530451}
452
453int clearInterface(int ifindex)
454{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700455 lg2::debug("ClearInterface , INTERFACE_INDEX : {INTERFACE_INDEX}",
456 "INTERFACE_INDEX", lg2::hex, ifindex);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500457 return internal::applyCmd(
458 ifindex, internal::Command(ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE));
Ratan Guptabbe45792018-03-23 00:22:55 +0530459}
460
Ratan Guptaaac603e2018-03-23 00:25:54 +0530461int getInfo(int ifindex, int package)
462{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700463 lg2::debug(
464 "Get Info , PACKAGE : {PACKAGE}, INTERFACE_INDEX: {INTERFACE_INDEX}",
465 "PACKAGE", lg2::hex, package, "INTERFACE_INDEX", lg2::hex, ifindex);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530466 if (package == DEFAULT_VALUE)
467 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500468 return internal::applyCmd(
469 ifindex, internal::Command(ncsi_nl_commands::NCSI_CMD_PKG_INFO),
470 package, DEFAULT_VALUE, NLM_F_DUMP, internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530471 }
472 else
473 {
474 return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
475 package, DEFAULT_VALUE, NONE,
476 internal::infoCallBack);
477 }
478}
479
Johnathan Mantey5a456062024-02-15 08:45:08 -0800480int setPackageMask(int ifindex, unsigned int mask)
481{
482 lg2::debug(
483 "Set Package Mask , INTERFACE_INDEX: {INTERFACE_INDEX} MASK: {MASK}",
484 "INTERFACE_INDEX", lg2::hex, ifindex, "MASK", lg2::hex, mask);
485 auto payload = std::span<const unsigned char>(
486 reinterpret_cast<const unsigned char*>(&mask),
487 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
488 return internal::applyCmd(
489 ifindex, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK,
490 0, payload));
491}
492
493int setChannelMask(int ifindex, int package, unsigned int mask)
494{
495 lg2::debug(
496 "Set Channel Mask , INTERFACE_INDEX: {INTERFACE_INDEX}, PACKAGE : {PACKAGE} MASK: {MASK}",
497 "INTERFACE_INDEX", lg2::hex, ifindex, "PACKAGE", lg2::hex, package,
498 "MASK", lg2::hex, mask);
499 auto payload = std::span<const unsigned char>(
500 reinterpret_cast<const unsigned char*>(&mask),
501 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
502 return internal::applyCmd(
503 ifindex,
504 internal::Command(ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK, 0,
505 payload),
506 package);
507 return 0;
508}
509
Gunnar Mills57d9c502018-09-14 14:42:34 -0500510} // namespace ncsi
511} // namespace network
512} // namespace phosphor