blob: c755d33ce69a17609ca44711ca58e98b962543a0 [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
Jeremy Kerrbea6cde2024-08-01 15:15:42 +080081CallBack infoCallBack = [](struct nl_msg* msg, void*) {
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
103 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
104 if (!tb[NCSI_ATTR_PACKAGE_LIST])
105 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700106 lg2::error("No Packages");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530107 return -1;
108 }
109
110 auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
111 if (!attrTgt)
112 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700113 lg2::error("Package list attribute is null");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530114 return -1;
115 }
116
117 auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
118 nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
119 {
120 ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
121 packagePolicy);
122 if (ret < 0)
123 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700124 lg2::error("Failed to parse package nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530125 return -1;
126 }
127
128 if (packagetb[NCSI_PKG_ATTR_ID])
129 {
130 auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700131 lg2::debug("Package has id : {ATTR_ID}", "ATTR_ID", lg2::hex,
132 attrID);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530133 }
134 else
135 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700136 lg2::debug("Package with no id");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530137 }
138
139 if (packagetb[NCSI_PKG_ATTR_FORCED])
140 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700141 lg2::debug("This package is forced");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530142 }
143
144 auto channelListTarget = static_cast<nlattr*>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500145 nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
Ratan Guptaaac603e2018-03-23 00:25:54 +0530146
147 auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
148 nla_for_each_nested(channelListTarget,
149 packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
150 {
151 ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
152 channelListTarget, channelPolicy);
153 if (ret < 0)
154 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700155 lg2::error("Failed to parse channel nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530156 return -1;
157 }
158
159 if (channeltb[NCSI_CHANNEL_ATTR_ID])
160 {
161 auto channel = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
162 if (channeltb[NCSI_CHANNEL_ATTR_ACTIVE])
163 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700164 lg2::debug("Channel Active : {CHANNEL}", "CHANNEL",
165 lg2::hex, channel);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530166 }
167 else
168 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700169 lg2::debug("Channel Not Active : {CHANNEL}", "CHANNEL",
170 lg2::hex, channel);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530171 }
172
173 if (channeltb[NCSI_CHANNEL_ATTR_FORCED])
174 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700175 lg2::debug("Channel is forced");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530176 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530177 }
178 else
179 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700180 lg2::debug("Channel with no ID");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530181 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530182
Ratan Guptaaac603e2018-03-23 00:25:54 +0530183 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
184 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500185 auto major =
186 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700187 lg2::debug("Channel Major Version : {CHANNEL_MAJOR_VERSION}",
188 "CHANNEL_MAJOR_VERSION", lg2::hex, major);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530189 }
190 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
191 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500192 auto minor =
193 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700194 lg2::debug("Channel Minor Version : {CHANNEL_MINOR_VERSION}",
195 "CHANNEL_MINOR_VERSION", lg2::hex, minor);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530196 }
197 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
198 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500199 auto str =
200 nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700201 lg2::debug("Channel Version Str : {CHANNEL_VERSION_STR}",
202 "CHANNEL_VERSION_STR", str);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530203 }
204 if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
205 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500206 auto link =
207 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700208 lg2::debug("Channel Link State : {LINK_STATE}", "LINK_STATE",
209 lg2::hex, link);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530210 }
211 if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
212 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700213 lg2::debug("Active Vlan ids");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530214 auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
215 auto vid = static_cast<nlattr*>(nla_data(vids));
216 auto len = nla_len(vids);
217 while (nla_ok(vid, len))
218 {
219 auto id = nla_get_u16(vid);
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700220 lg2::debug("VID : {VLAN_ID}", "VLAN_ID", id);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530221 vid = nla_next(vid, &len);
222 }
223 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530224 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530225 }
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800226 return static_cast<int>(NL_STOP);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530227};
228
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800229CallBack sendCallBack = [](struct nl_msg* msg, void*) {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500230 using namespace phosphor::network::ncsi;
231 auto nlh = nlmsg_hdr(msg);
232 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
233 static struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
234 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
235 {NLA_U32, 0, 0}, {NLA_U32, 0, 0}, {NLA_BINARY, 0, 0},
236 {NLA_FLAG, 0, 0}, {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
237 };
238
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500239 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
240 if (ret)
241 {
Jeremy Kerrde8d6662024-08-01 11:33:52 +0800242 lg2::error("Failed to parse message");
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500243 return ret;
244 }
245
Jian Zhang442d9e52022-10-20 22:11:14 +0800246 if (tb[NCSI_ATTR_DATA] == nullptr)
247 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700248 lg2::error("Response: No data");
Jian Zhang442d9e52022-10-20 22:11:14 +0800249 return -1;
250 }
251
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500252 auto data_len = nla_len(tb[NCSI_ATTR_DATA]) - sizeof(NCSIPacketHeader);
Patrick Williamsad205022024-08-16 15:20:07 -0400253 unsigned char* data =
254 (unsigned char*)nla_data(tb[NCSI_ATTR_DATA]) + sizeof(NCSIPacketHeader);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500255
256 // Dump the response to stdout. Enhancement: option to save response data
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700257 auto str = toHexStr(std::span<const unsigned char>(data, data_len));
258 lg2::debug("Response {DATA_LEN} bytes: {DATA}", "DATA_LEN", data_len,
259 "DATA", str);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500260
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800261 return static_cast<int>(NL_STOP);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500262};
263
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800264int applyCmd(Interface& interface, const Command& cmd,
265 int package = DEFAULT_VALUE, int channel = DEFAULT_VALUE,
266 int flags = NONE, CallBack function = nullptr)
Ratan Guptabbe45792018-03-23 00:22:55 +0530267{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500268 nlSocketPtr socket(nl_socket_alloc(), &::nl_socket_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700269 if (socket == nullptr)
270 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700271 lg2::error("Unable to allocate memory for the socket");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700272 return -ENOMEM;
273 }
274
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800275 nl_socket_disable_auto_ack(socket.get());
276
Ratan Guptabbe45792018-03-23 00:22:55 +0530277 auto ret = genl_connect(socket.get());
278 if (ret < 0)
279 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700280 lg2::error("Failed to open the socket , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530281 return ret;
282 }
283
284 auto driverID = genl_ctrl_resolve(socket.get(), "NCSI");
285 if (driverID < 0)
286 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700287 lg2::error("Failed to resolve, RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530288 return driverID;
289 }
290
291 nlMsgPtr msg(nlmsg_alloc(), &::nlmsg_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700292 if (msg == nullptr)
293 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700294 lg2::error("Unable to allocate memory for the message");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700295 return -ENOMEM;
296 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530297
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800298 auto msgHdr = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, driverID, 0,
299 flags, cmd.ncsi_cmd, 0);
Ratan Guptabbe45792018-03-23 00:22:55 +0530300 if (!msgHdr)
301 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700302 lg2::error("Unable to add the netlink headers , COMMAND : {COMMAND}",
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800303 "COMMAND", cmd.ncsi_cmd);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700304 return -ENOMEM;
Ratan Guptabbe45792018-03-23 00:22:55 +0530305 }
306
307 if (package != DEFAULT_VALUE)
308 {
309 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_PACKAGE_ID,
310 package);
311 if (ret < 0)
312 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700313 lg2::error("Failed to set the attribute , RC : {RC} PACKAGE "
314 "{PACKAGE}",
315 "RC", ret, "PACKAGE", lg2::hex, package);
Ratan Guptabbe45792018-03-23 00:22:55 +0530316 return ret;
317 }
318 }
319
320 if (channel != DEFAULT_VALUE)
321 {
322 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_CHANNEL_ID,
323 channel);
324 if (ret < 0)
325 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700326 lg2::error("Failed to set the attribute , RC : {RC} CHANNEL : "
327 "{CHANNEL}",
328 "RC", ret, "CHANNEL", lg2::hex, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530329 return ret;
330 }
331 }
332
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800333 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX,
334 interface.ifindex);
Ratan Guptabbe45792018-03-23 00:22:55 +0530335 if (ret < 0)
336 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700337 lg2::error("Failed to set the attribute , RC : {RC} INTERFACE : "
338 "{INTERFACE}",
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800339 "RC", ret, "INTERFACE", interface);
Ratan Guptabbe45792018-03-23 00:22:55 +0530340 return ret;
341 }
342
Johnathan Mantey5a456062024-02-15 08:45:08 -0800343 if ((cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK) ||
344 (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK))
345 {
346 if (cmd.payload.size() != sizeof(unsigned int))
347 {
348 lg2::error("Package/Channel mask must be 32-bits");
349 return -EINVAL;
350 }
351 int maskAttr =
352 cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK
353 ? NCSI_ATTR_PACKAGE_MASK
354 : NCSI_ATTR_CHANNEL_MASK;
355 ret = nla_put_u32(
356 msg.get(), maskAttr,
357 *(reinterpret_cast<const unsigned int*>(cmd.payload.data())));
358 if (ret < 0)
359 {
360 lg2::error("Failed to set the mask attribute, RC : {RC}", "RC",
361 ret);
362 return ret;
363 }
364 }
365 else if (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SEND_CMD)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500366 {
Patrick Williamsad205022024-08-16 15:20:07 -0400367 std::vector<unsigned char> pl(
368 sizeof(NCSIPacketHeader) + cmd.payload.size());
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500369 NCSIPacketHeader* hdr = (NCSIPacketHeader*)pl.data();
370
371 std::copy(cmd.payload.begin(), cmd.payload.end(),
372 pl.begin() + sizeof(NCSIPacketHeader));
373
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800374 hdr->type = cmd.operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500375 hdr->length = htons(cmd.payload.size());
376
377 ret = nla_put(msg.get(), ncsi_nl_attrs::NCSI_ATTR_DATA, pl.size(),
378 pl.data());
379 if (ret < 0)
380 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700381 lg2::error("Failed to set the data attribute, RC : {RC}", "RC",
382 ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500383 return ret;
384 }
385
386 nl_socket_disable_seq_check(socket.get());
387 }
388
Jeremy Kerr67b159a2024-08-01 15:23:57 +0800389 // Add a callback function to the socket
390 enum nl_cb_kind cb_kind = function ? NL_CB_CUSTOM : NL_CB_DEFAULT;
391 nl_socket_modify_cb(socket.get(), NL_CB_VALID, cb_kind, function, nullptr);
Ratan Guptabbe45792018-03-23 00:22:55 +0530392
393 ret = nl_send_auto(socket.get(), msg.get());
394 if (ret < 0)
395 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700396 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530397 return ret;
398 }
399
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800400 ret = nl_recvmsgs_default(socket.get());
401 if (ret < 0)
Ratan Guptabbe45792018-03-23 00:22:55 +0530402 {
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800403 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
404 return ret;
405 }
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500406
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800407 return 0;
Ratan Guptabbe45792018-03-23 00:22:55 +0530408}
409
Gunnar Mills57d9c502018-09-14 14:42:34 -0500410} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530411
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800412std::string to_string(Interface& interface)
413{
414 return std::to_string(interface.ifindex);
415}
416
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800417int Interface::sendOemCommand(int package, int channel, int operation,
418 std::span<const unsigned char> payload)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500419{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700420 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800421 "INTERFACE: {INTERFACE}",
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700422 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800423 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500424 if (!payload.empty())
425 {
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700426 lg2::debug("Payload: {PAYLOAD}", "PAYLOAD", toHexStr(payload));
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500427 }
428
429 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800430 *this,
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800431 internal::Command(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
432 payload),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500433 package, channel, NONE, internal::sendCallBack);
434}
435
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800436int Interface::setChannel(int package, int channel)
Ratan Guptabbe45792018-03-23 00:22:55 +0530437{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800438 lg2::debug("Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE : "
439 "{INTERFACE}",
440 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800441 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500442 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800443 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500444 package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530445}
446
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800447int Interface::clearInterface()
Ratan Guptabbe45792018-03-23 00:22:55 +0530448{
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800449 lg2::debug("ClearInterface , INTERFACE : {INTERFACE}", "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500450 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800451 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE));
Ratan Guptabbe45792018-03-23 00:22:55 +0530452}
453
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800454int Interface::getInfo(int package)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530455{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800456 lg2::debug("Get Info , PACKAGE : {PACKAGE}, INTERFACE: {INTERFACE}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800457 "PACKAGE", lg2::hex, package, "INTERFACE", this);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530458 if (package == DEFAULT_VALUE)
459 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500460 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800461 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_PKG_INFO),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500462 package, DEFAULT_VALUE, NLM_F_DUMP, internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530463 }
464 else
465 {
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800466 return internal::applyCmd(*this, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
467 package, DEFAULT_VALUE, NONE,
468 internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530469 }
470}
471
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800472int Interface::setPackageMask(unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800473{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800474 lg2::debug("Set Package Mask , INTERFACE: {INTERFACE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800475 "INTERFACE", this, "MASK", lg2::hex, mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800476 auto payload = std::span<const unsigned char>(
477 reinterpret_cast<const unsigned char*>(&mask),
478 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
479 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800480 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK, 0,
481 payload));
Johnathan Mantey5a456062024-02-15 08:45:08 -0800482}
483
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800484int Interface::setChannelMask(int package, unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800485{
486 lg2::debug(
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800487 "Set Channel Mask , INTERFACE: {INTERFACE}, PACKAGE : {PACKAGE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800488 "INTERFACE", this, "PACKAGE", lg2::hex, package, "MASK", lg2::hex,
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800489 mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800490 auto payload = std::span<const unsigned char>(
491 reinterpret_cast<const unsigned char*>(&mask),
492 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
493 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800494 *this,
Johnathan Mantey5a456062024-02-15 08:45:08 -0800495 internal::Command(ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK, 0,
496 payload),
497 package);
498 return 0;
499}
500
Gunnar Mills57d9c502018-09-14 14:42:34 -0500501} // namespace ncsi
502} // namespace network
503} // namespace phosphor