blob: 8c628aa92b94a65925c60c8c0ae417d7dd4aa6f9 [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 Kerr7f7c0852024-08-08 11:32:55 +080081struct infoCallBackContext
82{
83 InterfaceInfo* info;
84};
85
86CallBack infoCallBack = [](struct nl_msg* msg, void* arg) {
87 if (arg == nullptr)
88 {
89 lg2::error("Internal error: invalid info callback context");
90 return -1;
91 }
92
93 struct infoCallBackContext* info = (struct infoCallBackContext*)arg;
Ratan Guptaaac603e2018-03-23 00:25:54 +053094 using namespace phosphor::network::ncsi;
95 auto nlh = nlmsg_hdr(msg);
96
Gunnar Mills57d9c502018-09-14 14:42:34 -050097 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
98 struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070099 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
100 {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +0530101 };
102
Gunnar Mills57d9c502018-09-14 14:42:34 -0500103 struct nlattr* packagetb[NCSI_PKG_ATTR_MAX + 1] = {nullptr};
104 struct nla_policy packagePolicy[NCSI_PKG_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -0700105 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
106 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +0530107 };
108
Gunnar Mills57d9c502018-09-14 14:42:34 -0500109 struct nlattr* channeltb[NCSI_CHANNEL_ATTR_MAX + 1] = {nullptr};
110 struct nla_policy channelPolicy[NCSI_CHANNEL_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -0700111 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
112 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_UNSPEC, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +0530113 };
114
115 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
116 if (!tb[NCSI_ATTR_PACKAGE_LIST])
117 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700118 lg2::error("No Packages");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530119 return -1;
120 }
121
122 auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
123 if (!attrTgt)
124 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700125 lg2::error("Package list attribute is null");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530126 return -1;
127 }
128
129 auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
130 nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
131 {
132 ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
133 packagePolicy);
134 if (ret < 0)
135 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700136 lg2::error("Failed to parse package nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530137 return -1;
138 }
139
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800140 PackageInfo pkg;
141
Ratan Guptaaac603e2018-03-23 00:25:54 +0530142 if (packagetb[NCSI_PKG_ATTR_ID])
143 {
144 auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800145 pkg.id = attrID;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530146 }
147 else
148 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700149 lg2::debug("Package with no id");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530150 }
151
152 if (packagetb[NCSI_PKG_ATTR_FORCED])
153 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800154 pkg.forced = true;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530155 }
156
157 auto channelListTarget = static_cast<nlattr*>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500158 nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
Ratan Guptaaac603e2018-03-23 00:25:54 +0530159
160 auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
161 nla_for_each_nested(channelListTarget,
162 packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
163 {
164 ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
165 channelListTarget, channelPolicy);
166 if (ret < 0)
167 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700168 lg2::error("Failed to parse channel nested");
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800169 continue;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530170 }
171
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800172 ChannelInfo chan;
173
Ratan Guptaaac603e2018-03-23 00:25:54 +0530174 if (channeltb[NCSI_CHANNEL_ATTR_ID])
175 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800176 chan.id = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
177 chan.active = !!channeltb[NCSI_CHANNEL_ATTR_ACTIVE];
178 chan.forced = !!channeltb[NCSI_CHANNEL_ATTR_FORCED];
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");
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800183 continue;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530184 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530185
Ratan Guptaaac603e2018-03-23 00:25:54 +0530186 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
187 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800188 chan.version_major =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500189 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530190 }
191 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
192 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800193 chan.version_minor =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500194 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530195 }
196 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
197 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800198 chan.version =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500199 nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530200 }
201 if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
202 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800203 chan.link_state =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500204 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530205 }
206 if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
207 {
Ratan Guptaaac603e2018-03-23 00:25:54 +0530208 auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
209 auto vid = static_cast<nlattr*>(nla_data(vids));
210 auto len = nla_len(vids);
211 while (nla_ok(vid, len))
212 {
213 auto id = nla_get_u16(vid);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800214 chan.vlan_ids.push_back(id);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530215 vid = nla_next(vid, &len);
216 }
217 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800218 pkg.channels.push_back(chan);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530219 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800220
221 info->info->packages.push_back(pkg);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530222 }
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800223 return static_cast<int>(NL_STOP);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530224};
225
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800226CallBack sendCallBack = [](struct nl_msg* msg, void*) {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500227 using namespace phosphor::network::ncsi;
228 auto nlh = nlmsg_hdr(msg);
229 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
230 static struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
231 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
232 {NLA_U32, 0, 0}, {NLA_U32, 0, 0}, {NLA_BINARY, 0, 0},
233 {NLA_FLAG, 0, 0}, {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
234 };
235
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500236 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
237 if (ret)
238 {
Jeremy Kerrde8d6662024-08-01 11:33:52 +0800239 lg2::error("Failed to parse message");
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500240 return ret;
241 }
242
Jian Zhang442d9e52022-10-20 22:11:14 +0800243 if (tb[NCSI_ATTR_DATA] == nullptr)
244 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700245 lg2::error("Response: No data");
Jian Zhang442d9e52022-10-20 22:11:14 +0800246 return -1;
247 }
248
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500249 auto data_len = nla_len(tb[NCSI_ATTR_DATA]) - sizeof(NCSIPacketHeader);
Patrick Williamsad205022024-08-16 15:20:07 -0400250 unsigned char* data =
251 (unsigned char*)nla_data(tb[NCSI_ATTR_DATA]) + sizeof(NCSIPacketHeader);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500252
253 // Dump the response to stdout. Enhancement: option to save response data
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700254 auto str = toHexStr(std::span<const unsigned char>(data, data_len));
255 lg2::debug("Response {DATA_LEN} bytes: {DATA}", "DATA_LEN", data_len,
256 "DATA", str);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500257
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800258 return static_cast<int>(NL_STOP);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500259};
260
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800261int applyCmd(Interface& interface, const Command& cmd,
262 int package = DEFAULT_VALUE, int channel = DEFAULT_VALUE,
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800263 int flags = NONE, CallBack function = nullptr, void* arg = nullptr)
Ratan Guptabbe45792018-03-23 00:22:55 +0530264{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500265 nlSocketPtr socket(nl_socket_alloc(), &::nl_socket_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700266 if (socket == nullptr)
267 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700268 lg2::error("Unable to allocate memory for the socket");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700269 return -ENOMEM;
270 }
271
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800272 nl_socket_disable_auto_ack(socket.get());
273
Ratan Guptabbe45792018-03-23 00:22:55 +0530274 auto ret = genl_connect(socket.get());
275 if (ret < 0)
276 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700277 lg2::error("Failed to open the socket , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530278 return ret;
279 }
280
281 auto driverID = genl_ctrl_resolve(socket.get(), "NCSI");
282 if (driverID < 0)
283 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700284 lg2::error("Failed to resolve, RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530285 return driverID;
286 }
287
288 nlMsgPtr msg(nlmsg_alloc(), &::nlmsg_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700289 if (msg == nullptr)
290 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700291 lg2::error("Unable to allocate memory for the message");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700292 return -ENOMEM;
293 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530294
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800295 auto msgHdr = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, driverID, 0,
296 flags, cmd.ncsi_cmd, 0);
Ratan Guptabbe45792018-03-23 00:22:55 +0530297 if (!msgHdr)
298 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700299 lg2::error("Unable to add the netlink headers , COMMAND : {COMMAND}",
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800300 "COMMAND", cmd.ncsi_cmd);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700301 return -ENOMEM;
Ratan Guptabbe45792018-03-23 00:22:55 +0530302 }
303
304 if (package != DEFAULT_VALUE)
305 {
306 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_PACKAGE_ID,
307 package);
308 if (ret < 0)
309 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700310 lg2::error("Failed to set the attribute , RC : {RC} PACKAGE "
311 "{PACKAGE}",
312 "RC", ret, "PACKAGE", lg2::hex, package);
Ratan Guptabbe45792018-03-23 00:22:55 +0530313 return ret;
314 }
315 }
316
317 if (channel != DEFAULT_VALUE)
318 {
319 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_CHANNEL_ID,
320 channel);
321 if (ret < 0)
322 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700323 lg2::error("Failed to set the attribute , RC : {RC} CHANNEL : "
324 "{CHANNEL}",
325 "RC", ret, "CHANNEL", lg2::hex, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530326 return ret;
327 }
328 }
329
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800330 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX,
331 interface.ifindex);
Ratan Guptabbe45792018-03-23 00:22:55 +0530332 if (ret < 0)
333 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700334 lg2::error("Failed to set the attribute , RC : {RC} INTERFACE : "
335 "{INTERFACE}",
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800336 "RC", ret, "INTERFACE", interface);
Ratan Guptabbe45792018-03-23 00:22:55 +0530337 return ret;
338 }
339
Johnathan Mantey5a456062024-02-15 08:45:08 -0800340 if ((cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK) ||
341 (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK))
342 {
343 if (cmd.payload.size() != sizeof(unsigned int))
344 {
345 lg2::error("Package/Channel mask must be 32-bits");
346 return -EINVAL;
347 }
348 int maskAttr =
349 cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK
350 ? NCSI_ATTR_PACKAGE_MASK
351 : NCSI_ATTR_CHANNEL_MASK;
352 ret = nla_put_u32(
353 msg.get(), maskAttr,
354 *(reinterpret_cast<const unsigned int*>(cmd.payload.data())));
355 if (ret < 0)
356 {
357 lg2::error("Failed to set the mask attribute, RC : {RC}", "RC",
358 ret);
359 return ret;
360 }
361 }
362 else if (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SEND_CMD)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500363 {
Patrick Williamsad205022024-08-16 15:20:07 -0400364 std::vector<unsigned char> pl(
365 sizeof(NCSIPacketHeader) + cmd.payload.size());
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500366 NCSIPacketHeader* hdr = (NCSIPacketHeader*)pl.data();
367
368 std::copy(cmd.payload.begin(), cmd.payload.end(),
369 pl.begin() + sizeof(NCSIPacketHeader));
370
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800371 hdr->type = cmd.operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500372 hdr->length = htons(cmd.payload.size());
373
374 ret = nla_put(msg.get(), ncsi_nl_attrs::NCSI_ATTR_DATA, pl.size(),
375 pl.data());
376 if (ret < 0)
377 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700378 lg2::error("Failed to set the data attribute, RC : {RC}", "RC",
379 ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500380 return ret;
381 }
382
383 nl_socket_disable_seq_check(socket.get());
384 }
385
Jeremy Kerr67b159a2024-08-01 15:23:57 +0800386 // Add a callback function to the socket
387 enum nl_cb_kind cb_kind = function ? NL_CB_CUSTOM : NL_CB_DEFAULT;
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800388 nl_socket_modify_cb(socket.get(), NL_CB_VALID, cb_kind, function, arg);
Ratan Guptabbe45792018-03-23 00:22:55 +0530389
390 ret = nl_send_auto(socket.get(), msg.get());
391 if (ret < 0)
392 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700393 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530394 return ret;
395 }
396
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800397 ret = nl_recvmsgs_default(socket.get());
398 if (ret < 0)
Ratan Guptabbe45792018-03-23 00:22:55 +0530399 {
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800400 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
401 return ret;
402 }
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500403
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800404 return 0;
Ratan Guptabbe45792018-03-23 00:22:55 +0530405}
406
Gunnar Mills57d9c502018-09-14 14:42:34 -0500407} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530408
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800409std::string to_string(Interface& interface)
410{
411 return std::to_string(interface.ifindex);
412}
413
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800414int Interface::sendOemCommand(int package, int channel, int operation,
415 std::span<const unsigned char> payload)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500416{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700417 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800418 "INTERFACE: {INTERFACE}",
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700419 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800420 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500421 if (!payload.empty())
422 {
William A. Kennington IIIcbe50732023-07-25 13:52:18 -0700423 lg2::debug("Payload: {PAYLOAD}", "PAYLOAD", toHexStr(payload));
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500424 }
425
426 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800427 *this,
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800428 internal::Command(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
429 payload),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500430 package, channel, NONE, internal::sendCallBack);
431}
432
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800433int Interface::setChannel(int package, int channel)
Ratan Guptabbe45792018-03-23 00:22:55 +0530434{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800435 lg2::debug("Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE : "
436 "{INTERFACE}",
437 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800438 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500439 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800440 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE),
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500441 package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530442}
443
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800444int Interface::clearInterface()
Ratan Guptabbe45792018-03-23 00:22:55 +0530445{
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800446 lg2::debug("ClearInterface , INTERFACE : {INTERFACE}", "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500447 return internal::applyCmd(
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800448 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE));
Ratan Guptabbe45792018-03-23 00:22:55 +0530449}
450
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800451std::optional<InterfaceInfo> Interface::getInfo(int package)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530452{
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800453 int rc, flags = package == DEFAULT_VALUE ? NLM_F_DUMP : NONE;
454 InterfaceInfo info;
455
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);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800458
459 struct internal::infoCallBackContext ctx = {
460 .info = &info,
461 };
462
463 rc = internal::applyCmd(
464 *this, internal::Command(ncsi_nl_commands::NCSI_CMD_PKG_INFO), package,
465 DEFAULT_VALUE, flags, internal::infoCallBack, &ctx);
466
467 if (rc < 0)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530468 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800469 return {};
Ratan Guptaaac603e2018-03-23 00:25:54 +0530470 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800471
472 return info;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530473}
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