blob: b71451eae9ffeb0218051118c00291c0fe087097 [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
Ratan Guptaaac603e2018-03-23 00:25:54 +0530389 if (function)
390 {
391 // Add a callback function to the socket
Gunnar Mills57d9c502018-09-14 14:42:34 -0500392 nl_socket_modify_cb(socket.get(), NL_CB_VALID, NL_CB_CUSTOM, function,
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800393 nullptr);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530394 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530395
396 ret = nl_send_auto(socket.get(), msg.get());
397 if (ret < 0)
398 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700399 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530400 return ret;
401 }
402
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800403 ret = nl_recvmsgs_default(socket.get());
404 if (ret < 0)
Ratan Guptabbe45792018-03-23 00:22:55 +0530405 {
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800406 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
407 return ret;
408 }
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500409
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800410 return 0;
Ratan Guptabbe45792018-03-23 00:22:55 +0530411}
412
Gunnar Mills57d9c502018-09-14 14:42:34 -0500413} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530414
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800415std::string to_string(Interface& interface)
416{
417 return std::to_string(interface.ifindex);
418}
419
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800420int Interface::sendOemCommand(int package, int channel, int operation,
421 std::span<const unsigned char> payload)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500422{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700423 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800424 "INTERFACE: {INTERFACE}",
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700425 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800426 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500427 if (!payload.empty())
428 {
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700429 lg2::debug("Payload: {PAYLOAD}", "PAYLOAD", toHexStr(payload));
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500430 }
431
432 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800433 *this,
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800434 internal::Command(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
435 payload),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500436 package, channel, NONE, internal::sendCallBack);
437}
438
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800439int Interface::setChannel(int package, int channel)
Ratan Guptabbe45792018-03-23 00:22:55 +0530440{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800441 lg2::debug("Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE : "
442 "{INTERFACE}",
443 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800444 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500445 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800446 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500447 package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530448}
449
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800450int Interface::clearInterface()
Ratan Guptabbe45792018-03-23 00:22:55 +0530451{
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800452 lg2::debug("ClearInterface , INTERFACE : {INTERFACE}", "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_CLEAR_INTERFACE));
Ratan Guptabbe45792018-03-23 00:22:55 +0530455}
456
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800457int Interface::getInfo(int package)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530458{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800459 lg2::debug("Get Info , PACKAGE : {PACKAGE}, INTERFACE: {INTERFACE}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800460 "PACKAGE", lg2::hex, package, "INTERFACE", this);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530461 if (package == DEFAULT_VALUE)
462 {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500463 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800464 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_PKG_INFO),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500465 package, DEFAULT_VALUE, NLM_F_DUMP, internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530466 }
467 else
468 {
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800469 return internal::applyCmd(*this, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
470 package, DEFAULT_VALUE, NONE,
471 internal::infoCallBack);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530472 }
473}
474
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800475int Interface::setPackageMask(unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800476{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800477 lg2::debug("Set Package Mask , INTERFACE: {INTERFACE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800478 "INTERFACE", this, "MASK", lg2::hex, mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800479 auto payload = std::span<const unsigned char>(
480 reinterpret_cast<const unsigned char*>(&mask),
481 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
482 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800483 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK, 0,
484 payload));
Johnathan Mantey5a456062024-02-15 08:45:08 -0800485}
486
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800487int Interface::setChannelMask(int package, unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800488{
489 lg2::debug(
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800490 "Set Channel Mask , INTERFACE: {INTERFACE}, PACKAGE : {PACKAGE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800491 "INTERFACE", this, "PACKAGE", lg2::hex, package, "MASK", lg2::hex,
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800492 mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800493 auto payload = std::span<const unsigned char>(
494 reinterpret_cast<const unsigned char*>(&mask),
495 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
496 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800497 *this,
Johnathan Mantey5a456062024-02-15 08:45:08 -0800498 internal::Command(ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK, 0,
499 payload),
500 package);
501 return 0;
502}
503
Gunnar Mills57d9c502018-09-14 14:42:34 -0500504} // namespace ncsi
505} // namespace network
506} // namespace phosphor