blob: 13c41f6d6007b768b35ca09854284b1a264ae1b8 [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>
9
Jiaqing Zhao7c44a782022-04-10 15:30:04 +080010#include <vector>
Ratan Guptabbe45792018-03-23 00:22:55 +053011
12namespace phosphor
13{
14namespace network
15{
16namespace ncsi
17{
18
Gunnar Mills57d9c502018-09-14 14:42:34 -050019using CallBack = int (*)(struct nl_msg* msg, void* arg);
Ratan Guptaaac603e2018-03-23 00:25:54 +053020
21namespace internal
22{
Ratan Guptabbe45792018-03-23 00:22:55 +053023
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050024struct NCSIPacketHeader
25{
26 uint8_t MCID;
27 uint8_t revision;
28 uint8_t reserved;
29 uint8_t id;
30 uint8_t type;
31 uint8_t channel;
32 uint16_t length;
33 uint32_t rsvd[2];
34};
35
Jeremy Kerr3f34ff62024-09-12 13:00:27 +080036class NetlinkCommand
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050037{
38 public:
Jeremy Kerr3f34ff62024-09-12 13:00:27 +080039 NetlinkCommand() = delete;
40 ~NetlinkCommand() = default;
41 NetlinkCommand(const NetlinkCommand&) = delete;
42 NetlinkCommand& operator=(const NetlinkCommand&) = delete;
43 NetlinkCommand(NetlinkCommand&&) = default;
44 NetlinkCommand& operator=(NetlinkCommand&&) = default;
45 NetlinkCommand(
Johnathan Mantey1ebea282024-02-15 10:26:06 -080046 int ncsiCmd, int operation = DEFAULT_VALUE,
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050047 std::span<const unsigned char> p = std::span<const unsigned char>()) :
Patrick Williamsad205022024-08-16 15:20:07 -040048 ncsi_cmd(ncsiCmd), operation(operation), payload(p)
Patrick Williams89d734b2023-05-10 07:50:25 -050049 {}
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050050
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050051 int ncsi_cmd;
Johnathan Mantey1ebea282024-02-15 10:26:06 -080052 int operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -050053 std::span<const unsigned char> payload;
54};
55
Ratan Guptabbe45792018-03-23 00:22:55 +053056using nlMsgPtr = std::unique_ptr<nl_msg, decltype(&::nlmsg_free)>;
57using nlSocketPtr = std::unique_ptr<nl_sock, decltype(&::nl_socket_free)>;
58
Jeremy Kerr7f7c0852024-08-08 11:32:55 +080059struct infoCallBackContext
60{
61 InterfaceInfo* info;
62};
63
64CallBack infoCallBack = [](struct nl_msg* msg, void* arg) {
65 if (arg == nullptr)
66 {
67 lg2::error("Internal error: invalid info callback context");
68 return -1;
69 }
70
71 struct infoCallBackContext* info = (struct infoCallBackContext*)arg;
Ratan Guptaaac603e2018-03-23 00:25:54 +053072 using namespace phosphor::network::ncsi;
73 auto nlh = nlmsg_hdr(msg);
74
Gunnar Mills57d9c502018-09-14 14:42:34 -050075 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
76 struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070077 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
78 {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +053079 };
80
Gunnar Mills57d9c502018-09-14 14:42:34 -050081 struct nlattr* packagetb[NCSI_PKG_ATTR_MAX + 1] = {nullptr};
82 struct nla_policy packagePolicy[NCSI_PKG_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070083 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
84 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +053085 };
86
Gunnar Mills57d9c502018-09-14 14:42:34 -050087 struct nlattr* channeltb[NCSI_CHANNEL_ATTR_MAX + 1] = {nullptr};
88 struct nla_policy channelPolicy[NCSI_CHANNEL_ATTR_MAX + 1] = {
William A. Kennington III05368f12021-05-13 18:40:47 -070089 {NLA_UNSPEC, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_U32, 0, 0},
90 {NLA_FLAG, 0, 0}, {NLA_NESTED, 0, 0}, {NLA_UNSPEC, 0, 0},
Ratan Guptaaac603e2018-03-23 00:25:54 +053091 };
92
93 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
94 if (!tb[NCSI_ATTR_PACKAGE_LIST])
95 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -070096 lg2::error("No Packages");
Ratan Guptaaac603e2018-03-23 00:25:54 +053097 return -1;
98 }
99
100 auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
101 if (!attrTgt)
102 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700103 lg2::error("Package list attribute is null");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530104 return -1;
105 }
106
107 auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
108 nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
109 {
110 ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
111 packagePolicy);
112 if (ret < 0)
113 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700114 lg2::error("Failed to parse package nested");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530115 return -1;
116 }
117
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800118 PackageInfo pkg;
119
Ratan Guptaaac603e2018-03-23 00:25:54 +0530120 if (packagetb[NCSI_PKG_ATTR_ID])
121 {
122 auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800123 pkg.id = attrID;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530124 }
125 else
126 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700127 lg2::debug("Package with no id");
Ratan Guptaaac603e2018-03-23 00:25:54 +0530128 }
129
130 if (packagetb[NCSI_PKG_ATTR_FORCED])
131 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800132 pkg.forced = true;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530133 }
134
135 auto channelListTarget = static_cast<nlattr*>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500136 nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
Ratan Guptaaac603e2018-03-23 00:25:54 +0530137
138 auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
139 nla_for_each_nested(channelListTarget,
140 packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
141 {
142 ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
143 channelListTarget, channelPolicy);
144 if (ret < 0)
145 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700146 lg2::error("Failed to parse channel nested");
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800147 continue;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530148 }
149
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800150 ChannelInfo chan;
151
Ratan Guptaaac603e2018-03-23 00:25:54 +0530152 if (channeltb[NCSI_CHANNEL_ATTR_ID])
153 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800154 chan.id = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
155 chan.active = !!channeltb[NCSI_CHANNEL_ATTR_ACTIVE];
156 chan.forced = !!channeltb[NCSI_CHANNEL_ATTR_FORCED];
Ratan Guptaaac603e2018-03-23 00:25:54 +0530157 }
158 else
159 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700160 lg2::debug("Channel with no ID");
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800161 continue;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530162 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530163
Ratan Guptaaac603e2018-03-23 00:25:54 +0530164 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
165 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800166 chan.version_major =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500167 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530168 }
169 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
170 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800171 chan.version_minor =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500172 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530173 }
174 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
175 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800176 chan.version =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500177 nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530178 }
179 if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
180 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800181 chan.link_state =
Gunnar Mills57d9c502018-09-14 14:42:34 -0500182 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530183 }
184 if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
185 {
Ratan Guptaaac603e2018-03-23 00:25:54 +0530186 auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
187 auto vid = static_cast<nlattr*>(nla_data(vids));
188 auto len = nla_len(vids);
189 while (nla_ok(vid, len))
190 {
191 auto id = nla_get_u16(vid);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800192 chan.vlan_ids.push_back(id);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530193 vid = nla_next(vid, &len);
194 }
195 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800196 pkg.channels.push_back(chan);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530197 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800198
199 info->info->packages.push_back(pkg);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530200 }
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800201 return static_cast<int>(NL_STOP);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530202};
203
Jeremy Kerr147086d2024-08-27 13:46:38 +0800204struct sendCallBackContext
205{
206 std::vector<unsigned char> msg;
207};
208
209CallBack sendCallBack = [](struct nl_msg* msg, void* arg) {
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500210 using namespace phosphor::network::ncsi;
211 auto nlh = nlmsg_hdr(msg);
212 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
213 static struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
214 {NLA_UNSPEC, 0, 0}, {NLA_U32, 0, 0}, {NLA_NESTED, 0, 0},
215 {NLA_U32, 0, 0}, {NLA_U32, 0, 0}, {NLA_BINARY, 0, 0},
216 {NLA_FLAG, 0, 0}, {NLA_U32, 0, 0}, {NLA_U32, 0, 0},
217 };
218
Jeremy Kerr147086d2024-08-27 13:46:38 +0800219 if (arg == nullptr)
220 {
221 lg2::error("Internal error: invalid send callback context");
222 return -1;
223 }
224
225 struct sendCallBackContext* ctx = (struct sendCallBackContext*)arg;
226
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500227 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
228 if (ret)
229 {
Jeremy Kerrde8d6662024-08-01 11:33:52 +0800230 lg2::error("Failed to parse message");
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500231 return ret;
232 }
233
Jian Zhang442d9e52022-10-20 22:11:14 +0800234 if (tb[NCSI_ATTR_DATA] == nullptr)
235 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700236 lg2::error("Response: No data");
Jian Zhang442d9e52022-10-20 22:11:14 +0800237 return -1;
238 }
239
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500240 auto data_len = nla_len(tb[NCSI_ATTR_DATA]) - sizeof(NCSIPacketHeader);
Patrick Williamsad205022024-08-16 15:20:07 -0400241 unsigned char* data =
242 (unsigned char*)nla_data(tb[NCSI_ATTR_DATA]) + sizeof(NCSIPacketHeader);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500243
Jeremy Kerr147086d2024-08-27 13:46:38 +0800244 ctx->msg.assign(data, data + data_len);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500245
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800246 return static_cast<int>(NL_STOP);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500247};
248
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800249int applyCmd(Interface& interface, const NetlinkCommand& cmd,
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800250 int package = DEFAULT_VALUE, int channel = DEFAULT_VALUE,
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800251 int flags = NONE, CallBack function = nullptr, void* arg = nullptr)
Ratan Guptabbe45792018-03-23 00:22:55 +0530252{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500253 nlSocketPtr socket(nl_socket_alloc(), &::nl_socket_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700254 if (socket == nullptr)
255 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700256 lg2::error("Unable to allocate memory for the socket");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700257 return -ENOMEM;
258 }
259
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800260 nl_socket_disable_auto_ack(socket.get());
261
Ratan Guptabbe45792018-03-23 00:22:55 +0530262 auto ret = genl_connect(socket.get());
263 if (ret < 0)
264 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700265 lg2::error("Failed to open the socket , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530266 return ret;
267 }
268
269 auto driverID = genl_ctrl_resolve(socket.get(), "NCSI");
270 if (driverID < 0)
271 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700272 lg2::error("Failed to resolve, RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530273 return driverID;
274 }
275
276 nlMsgPtr msg(nlmsg_alloc(), &::nlmsg_free);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700277 if (msg == nullptr)
278 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700279 lg2::error("Unable to allocate memory for the message");
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700280 return -ENOMEM;
281 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530282
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800283 auto msgHdr = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, driverID, 0,
284 flags, cmd.ncsi_cmd, 0);
Ratan Guptabbe45792018-03-23 00:22:55 +0530285 if (!msgHdr)
286 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700287 lg2::error("Unable to add the netlink headers , COMMAND : {COMMAND}",
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800288 "COMMAND", cmd.ncsi_cmd);
Johnathan Manteyd49c5c62021-06-23 09:14:42 -0700289 return -ENOMEM;
Ratan Guptabbe45792018-03-23 00:22:55 +0530290 }
291
292 if (package != DEFAULT_VALUE)
293 {
294 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_PACKAGE_ID,
295 package);
296 if (ret < 0)
297 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700298 lg2::error("Failed to set the attribute , RC : {RC} PACKAGE "
299 "{PACKAGE}",
300 "RC", ret, "PACKAGE", lg2::hex, package);
Ratan Guptabbe45792018-03-23 00:22:55 +0530301 return ret;
302 }
303 }
304
305 if (channel != DEFAULT_VALUE)
306 {
307 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_CHANNEL_ID,
308 channel);
309 if (ret < 0)
310 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700311 lg2::error("Failed to set the attribute , RC : {RC} CHANNEL : "
312 "{CHANNEL}",
313 "RC", ret, "CHANNEL", lg2::hex, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530314 return ret;
315 }
316 }
317
Jeremy Kerr8d9af022024-07-26 16:47:16 +0800318 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX,
319 interface.ifindex);
Ratan Guptabbe45792018-03-23 00:22:55 +0530320 if (ret < 0)
321 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700322 lg2::error("Failed to set the attribute , RC : {RC} INTERFACE : "
323 "{INTERFACE}",
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800324 "RC", ret, "INTERFACE", interface);
Ratan Guptabbe45792018-03-23 00:22:55 +0530325 return ret;
326 }
327
Johnathan Mantey5a456062024-02-15 08:45:08 -0800328 if ((cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK) ||
329 (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK))
330 {
331 if (cmd.payload.size() != sizeof(unsigned int))
332 {
333 lg2::error("Package/Channel mask must be 32-bits");
334 return -EINVAL;
335 }
336 int maskAttr =
337 cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK
338 ? NCSI_ATTR_PACKAGE_MASK
339 : NCSI_ATTR_CHANNEL_MASK;
340 ret = nla_put_u32(
341 msg.get(), maskAttr,
342 *(reinterpret_cast<const unsigned int*>(cmd.payload.data())));
343 if (ret < 0)
344 {
345 lg2::error("Failed to set the mask attribute, RC : {RC}", "RC",
346 ret);
347 return ret;
348 }
349 }
350 else if (cmd.ncsi_cmd == ncsi_nl_commands::NCSI_CMD_SEND_CMD)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500351 {
Patrick Williamsad205022024-08-16 15:20:07 -0400352 std::vector<unsigned char> pl(
353 sizeof(NCSIPacketHeader) + cmd.payload.size());
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500354 NCSIPacketHeader* hdr = (NCSIPacketHeader*)pl.data();
355
356 std::copy(cmd.payload.begin(), cmd.payload.end(),
357 pl.begin() + sizeof(NCSIPacketHeader));
358
Johnathan Mantey1ebea282024-02-15 10:26:06 -0800359 hdr->type = cmd.operation;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500360 hdr->length = htons(cmd.payload.size());
361
362 ret = nla_put(msg.get(), ncsi_nl_attrs::NCSI_ATTR_DATA, pl.size(),
363 pl.data());
364 if (ret < 0)
365 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700366 lg2::error("Failed to set the data attribute, RC : {RC}", "RC",
367 ret);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500368 return ret;
369 }
370
371 nl_socket_disable_seq_check(socket.get());
372 }
373
Jeremy Kerr67b159a2024-08-01 15:23:57 +0800374 // Add a callback function to the socket
375 enum nl_cb_kind cb_kind = function ? NL_CB_CUSTOM : NL_CB_DEFAULT;
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800376 nl_socket_modify_cb(socket.get(), NL_CB_VALID, cb_kind, function, arg);
Ratan Guptabbe45792018-03-23 00:22:55 +0530377
378 ret = nl_send_auto(socket.get(), msg.get());
379 if (ret < 0)
380 {
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700381 lg2::error("Failed to send the message , RC : {RC}", "RC", ret);
Ratan Guptabbe45792018-03-23 00:22:55 +0530382 return ret;
383 }
384
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800385 ret = nl_recvmsgs_default(socket.get());
386 if (ret < 0)
Ratan Guptabbe45792018-03-23 00:22:55 +0530387 {
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800388 lg2::error("Failed to receive the message , RC : {RC}", "RC", ret);
389 return ret;
390 }
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500391
Jeremy Kerrbea6cde2024-08-01 15:15:42 +0800392 return 0;
Ratan Guptabbe45792018-03-23 00:22:55 +0530393}
394
Gunnar Mills57d9c502018-09-14 14:42:34 -0500395} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530396
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800397std::string to_string(Interface& interface)
398{
399 return std::to_string(interface.ifindex);
400}
401
Jeremy Kerr147086d2024-08-27 13:46:38 +0800402std::optional<std::vector<unsigned char>>
403 Interface::sendOemCommand(int package, int channel, int operation,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800404 std::span<const unsigned char> payload)
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500405{
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700406 lg2::debug("Send OEM Command, CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, "
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800407 "INTERFACE: {INTERFACE}",
Jagpal Singh Gilld423beb2023-04-18 11:28:03 -0700408 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800409 "INTERFACE", this);
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500410
Jeremy Kerr147086d2024-08-27 13:46:38 +0800411 internal::sendCallBackContext ctx{};
412
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800413 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_SEND_CMD, operation,
414 payload);
415
416 int rc = internal::applyCmd(*this, cmd, package, channel, NONE,
417 internal::sendCallBack, &ctx);
Jeremy Kerr147086d2024-08-27 13:46:38 +0800418
419 if (rc < 0)
420 {
421 return {};
422 }
423
424 return ctx.msg;
Eddie Jamesfa1f5c02020-09-17 15:12:46 -0500425}
426
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800427int Interface::setChannel(int package, int channel)
Ratan Guptabbe45792018-03-23 00:22:55 +0530428{
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800429 lg2::debug("Set CHANNEL : {CHANNEL} , PACKAGE : {PACKAGE}, INTERFACE : "
430 "{INTERFACE}",
431 "CHANNEL", lg2::hex, channel, "PACKAGE", lg2::hex, package,
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800432 "INTERFACE", this);
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800433
434 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_SET_INTERFACE);
435
436 return internal::applyCmd(*this, cmd, package, channel);
Ratan Guptabbe45792018-03-23 00:22:55 +0530437}
438
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800439int Interface::clearInterface()
Ratan Guptabbe45792018-03-23 00:22:55 +0530440{
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800441 lg2::debug("ClearInterface , INTERFACE : {INTERFACE}", "INTERFACE", this);
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800442
443 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE);
444 return internal::applyCmd(*this, cmd);
Ratan Guptabbe45792018-03-23 00:22:55 +0530445}
446
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800447std::optional<InterfaceInfo> Interface::getInfo(int package)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530448{
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800449 int rc, flags = package == DEFAULT_VALUE ? NLM_F_DUMP : NONE;
450 InterfaceInfo info;
451
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800452 lg2::debug("Get Info , PACKAGE : {PACKAGE}, INTERFACE: {INTERFACE}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800453 "PACKAGE", lg2::hex, package, "INTERFACE", this);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800454
455 struct internal::infoCallBackContext ctx = {
456 .info = &info,
457 };
458
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800459 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_PKG_INFO);
460
461 rc = internal::applyCmd(*this, cmd, package, DEFAULT_VALUE, flags,
462 internal::infoCallBack, &ctx);
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800463
464 if (rc < 0)
Ratan Guptaaac603e2018-03-23 00:25:54 +0530465 {
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800466 return {};
Ratan Guptaaac603e2018-03-23 00:25:54 +0530467 }
Jeremy Kerr7f7c0852024-08-08 11:32:55 +0800468
469 return info;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530470}
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)));
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800479
480 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_SET_PACKAGE_MASK, 0,
481 payload);
482 return internal::applyCmd(*this, cmd);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800483}
484
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800485int Interface::setChannelMask(int package, unsigned int mask)
Johnathan Mantey5a456062024-02-15 08:45:08 -0800486{
487 lg2::debug(
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800488 "Set Channel Mask , INTERFACE: {INTERFACE}, PACKAGE : {PACKAGE} MASK: {MASK}",
Jeremy Kerrbc22f812024-07-29 17:43:35 +0800489 "INTERFACE", this, "PACKAGE", lg2::hex, package, "MASK", lg2::hex,
Jeremy Kerr8a76d892024-07-26 17:19:57 +0800490 mask);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800491 auto payload = std::span<const unsigned char>(
492 reinterpret_cast<const unsigned char*>(&mask),
493 reinterpret_cast<const unsigned char*>(&mask) + sizeof(decltype(mask)));
Jeremy Kerr3f34ff62024-09-12 13:00:27 +0800494
495 internal::NetlinkCommand cmd(ncsi_nl_commands::NCSI_CMD_SET_CHANNEL_MASK, 0,
496 payload);
497 return internal::applyCmd(*this, cmd);
Johnathan Mantey5a456062024-02-15 08:45:08 -0800498}
499
Gunnar Mills57d9c502018-09-14 14:42:34 -0500500} // namespace ncsi
501} // namespace network
502} // namespace phosphor