blob: 4c5d6ac5d3bf130b7905a39446c11cf5269a9727 [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
Manojkiran Edae5a867a2020-06-01 18:08:30 +05308#include <iostream>
Ratan Guptabbe45792018-03-23 00:22:55 +05309#include <phosphor-logging/elog-errors.hpp>
10#include <phosphor-logging/log.hpp>
Patrick Venture189d44e2018-07-09 12:30:59 -070011#include <xyz/openbmc_project/Common/error.hpp>
Ratan Guptabbe45792018-03-23 00:22:55 +053012
13namespace phosphor
14{
15namespace network
16{
17namespace ncsi
18{
19
20using namespace phosphor::logging;
21using namespace sdbusplus::xyz::openbmc_project::Common::Error;
22
Gunnar Mills57d9c502018-09-14 14:42:34 -050023using CallBack = int (*)(struct nl_msg* msg, void* arg);
Ratan Guptaaac603e2018-03-23 00:25:54 +053024
25namespace internal
26{
Ratan Guptabbe45792018-03-23 00:22:55 +053027
28using nlMsgPtr = std::unique_ptr<nl_msg, decltype(&::nlmsg_free)>;
29using nlSocketPtr = std::unique_ptr<nl_sock, decltype(&::nl_socket_free)>;
30
Manojkiran Edaaa57fa52020-06-13 14:59:53 +053031CallBack infoCallBack = [](struct nl_msg* msg, void* /*arg*/) {
Ratan Guptaaac603e2018-03-23 00:25:54 +053032 using namespace phosphor::network::ncsi;
33 auto nlh = nlmsg_hdr(msg);
34
Gunnar Mills57d9c502018-09-14 14:42:34 -050035 struct nlattr* tb[NCSI_ATTR_MAX + 1] = {nullptr};
36 struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] = {
37 {type : NLA_UNSPEC}, {type : NLA_U32}, {type : NLA_NESTED},
38 {type : NLA_U32}, {type : NLA_U32},
Ratan Guptaaac603e2018-03-23 00:25:54 +053039 };
40
Gunnar Mills57d9c502018-09-14 14:42:34 -050041 struct nlattr* packagetb[NCSI_PKG_ATTR_MAX + 1] = {nullptr};
42 struct nla_policy packagePolicy[NCSI_PKG_ATTR_MAX + 1] = {
43 {type : NLA_UNSPEC}, {type : NLA_NESTED}, {type : NLA_U32},
44 {type : NLA_FLAG}, {type : NLA_NESTED},
Ratan Guptaaac603e2018-03-23 00:25:54 +053045 };
46
Gunnar Mills57d9c502018-09-14 14:42:34 -050047 struct nlattr* channeltb[NCSI_CHANNEL_ATTR_MAX + 1] = {nullptr};
48 struct nla_policy channelPolicy[NCSI_CHANNEL_ATTR_MAX + 1] = {
49 {type : NLA_UNSPEC}, {type : NLA_NESTED}, {type : NLA_U32},
50 {type : NLA_FLAG}, {type : NLA_NESTED}, {type : NLA_UNSPEC},
Ratan Guptaaac603e2018-03-23 00:25:54 +053051 };
52
53 auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
54 if (!tb[NCSI_ATTR_PACKAGE_LIST])
55 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +053056 std::cerr << "No Packages" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053057 return -1;
58 }
59
60 auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
61 if (!attrTgt)
62 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +053063 std::cerr << "Package list attribute is null" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053064 return -1;
65 }
66
67 auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
68 nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
69 {
70 ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
71 packagePolicy);
72 if (ret < 0)
73 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +053074 std::cerr << "Failed to parse package nested" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053075 return -1;
76 }
77
78 if (packagetb[NCSI_PKG_ATTR_ID])
79 {
80 auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
Manojkiran Edae5a867a2020-06-01 18:08:30 +053081 std::cout << "Package has id : " << std::hex << attrID << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053082 }
83 else
84 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +053085 std::cout << "Package with no id" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053086 }
87
88 if (packagetb[NCSI_PKG_ATTR_FORCED])
89 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +053090 std::cout << "This package is forced" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +053091 }
92
93 auto channelListTarget = static_cast<nlattr*>(
Gunnar Mills57d9c502018-09-14 14:42:34 -050094 nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
Ratan Guptaaac603e2018-03-23 00:25:54 +053095
96 auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
97 nla_for_each_nested(channelListTarget,
98 packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
99 {
100 ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
101 channelListTarget, channelPolicy);
102 if (ret < 0)
103 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530104 std::cerr << "Failed to parse channel nested" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530105 return -1;
106 }
107
108 if (channeltb[NCSI_CHANNEL_ATTR_ID])
109 {
110 auto channel = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
111 if (channeltb[NCSI_CHANNEL_ATTR_ACTIVE])
112 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530113 std::cout << "Channel Active : " << std::hex << channel
114 << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530115 }
116 else
117 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530118 std::cout << "Channel Not Active : " << std::hex << channel
119 << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530120 }
121
122 if (channeltb[NCSI_CHANNEL_ATTR_FORCED])
123 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530124 std::cout << "Channel is forced" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530125 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530126 }
127 else
128 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530129 std::cout << "Channel with no ID" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530130 }
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530131
Ratan Guptaaac603e2018-03-23 00:25:54 +0530132 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
133 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500134 auto major =
135 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530136 std::cout << "Channel Major Version : " << std::hex << major
137 << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530138 }
139 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
140 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500141 auto minor =
142 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530143 std::cout << "Channel Minor Version : " << std::hex << minor
144 << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530145 }
146 if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
147 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500148 auto str =
149 nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530150 std::cout << "Channel Version Str :" << str << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530151 }
152 if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
153 {
Ratan Guptaed5d7ff2018-03-23 00:27:52 +0530154
Gunnar Mills57d9c502018-09-14 14:42:34 -0500155 auto link =
156 nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530157 std::cout << "Channel Link State : " << std::hex << link
158 << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530159 }
160 if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
161 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530162 std::cout << "Active Vlan ids" << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530163 auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
164 auto vid = static_cast<nlattr*>(nla_data(vids));
165 auto len = nla_len(vids);
166 while (nla_ok(vid, len))
167 {
168 auto id = nla_get_u16(vid);
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530169 std::cout << "VID : " << id << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530170 vid = nla_next(vid, &len);
171 }
172 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530173 }
Ratan Guptaaac603e2018-03-23 00:25:54 +0530174 }
175 return (int)NL_SKIP;
176};
177
Ratan Guptabbe45792018-03-23 00:22:55 +0530178int applyCmd(int ifindex, int cmd, int package = DEFAULT_VALUE,
Ratan Guptaaac603e2018-03-23 00:25:54 +0530179 int channel = DEFAULT_VALUE, int flags = NONE,
180 CallBack function = nullptr)
Ratan Guptabbe45792018-03-23 00:22:55 +0530181{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500182 nlSocketPtr socket(nl_socket_alloc(), &::nl_socket_free);
Ratan Guptabbe45792018-03-23 00:22:55 +0530183 auto ret = genl_connect(socket.get());
184 if (ret < 0)
185 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530186 std::cerr << "Failed to open the socket , RC : " << ret << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530187 return ret;
188 }
189
190 auto driverID = genl_ctrl_resolve(socket.get(), "NCSI");
191 if (driverID < 0)
192 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530193 std::cerr << "Failed to resolve, RC : " << ret << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530194 return driverID;
195 }
196
197 nlMsgPtr msg(nlmsg_alloc(), &::nlmsg_free);
198
Gunnar Mills57d9c502018-09-14 14:42:34 -0500199 auto msgHdr = genlmsg_put(msg.get(), 0, 0, driverID, 0, flags, cmd, 0);
Ratan Guptabbe45792018-03-23 00:22:55 +0530200 if (!msgHdr)
201 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530202 std::cerr << "Unable to add the netlink headers , COMMAND : " << cmd
203 << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530204 return -1;
205 }
206
207 if (package != DEFAULT_VALUE)
208 {
209 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_PACKAGE_ID,
210 package);
211 if (ret < 0)
212 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530213 std::cerr << "Failed to set the attribute , RC : " << ret
214 << "PACKAGE " << std::hex << package << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530215 return ret;
216 }
217 }
218
219 if (channel != DEFAULT_VALUE)
220 {
221 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_CHANNEL_ID,
222 channel);
223 if (ret < 0)
224 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530225 std::cerr << "Failed to set the attribute , RC : " << ret
226 << "CHANNEL : " << std::hex << channel << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530227 return ret;
228 }
229 }
230
231 ret = nla_put_u32(msg.get(), ncsi_nl_attrs::NCSI_ATTR_IFINDEX, ifindex);
232 if (ret < 0)
233 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530234 std::cerr << "Failed to set the attribute , RC : " << ret
235 << "INTERFACE : " << std::hex << ifindex << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530236 return ret;
237 }
238
Ratan Guptaaac603e2018-03-23 00:25:54 +0530239 if (function)
240 {
241 // Add a callback function to the socket
Gunnar Mills57d9c502018-09-14 14:42:34 -0500242 nl_socket_modify_cb(socket.get(), NL_CB_VALID, NL_CB_CUSTOM, function,
243 nullptr);
Ratan Guptaaac603e2018-03-23 00:25:54 +0530244 }
Ratan Guptabbe45792018-03-23 00:22:55 +0530245
246 ret = nl_send_auto(socket.get(), msg.get());
247 if (ret < 0)
248 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530249 std::cerr << "Failed to send the message , RC : " << ret << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530250 return ret;
251 }
252
253 ret = nl_recvmsgs_default(socket.get());
254 if (ret < 0)
255 {
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530256 std::cerr << "Failed to receive the message , RC : " << ret
257 << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530258 }
259 return ret;
260}
261
Gunnar Mills57d9c502018-09-14 14:42:34 -0500262} // namespace internal
Ratan Guptabbe45792018-03-23 00:22:55 +0530263
264int setChannel(int ifindex, int package, int channel)
265{
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530266 std::cout << "Set Channel : " << std::hex << channel
267 << ", PACKAGE : " << std::hex << package
268 << ", IFINDEX : " << std::hex << ifindex << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530269 return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_SET_INTERFACE,
270 package, channel);
271}
272
273int clearInterface(int ifindex)
274{
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530275 std::cout << "ClearInterface , IFINDEX :" << std::hex << ifindex
276 << std::endl;
Ratan Guptabbe45792018-03-23 00:22:55 +0530277 return internal::applyCmd(ifindex,
278 ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE);
279}
280
Ratan Guptaaac603e2018-03-23 00:25:54 +0530281int getInfo(int ifindex, int package)
282{
Manojkiran Edae5a867a2020-06-01 18:08:30 +0530283 std::cout << "Get Info , PACKAGE : " << std::hex << package
284 << ", IFINDEX : " << std::hex << ifindex << std::endl;
Ratan Guptaaac603e2018-03-23 00:25:54 +0530285 if (package == DEFAULT_VALUE)
286 {
287 return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
288 package, DEFAULT_VALUE, NLM_F_DUMP,
289 internal::infoCallBack);
290 }
291 else
292 {
293 return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
294 package, DEFAULT_VALUE, NONE,
295 internal::infoCallBack);
296 }
297}
298
Gunnar Mills57d9c502018-09-14 14:42:34 -0500299} // namespace ncsi
300} // namespace network
301} // namespace phosphor