summaryrefslogtreecommitdiffstats
path: root/ncsi_util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ncsi_util.cpp')
-rw-r--r--ncsi_util.cpp195
1 files changed, 191 insertions, 4 deletions
diff --git a/ncsi_util.cpp b/ncsi_util.cpp
index f05cc0b..bf19ee3 100644
--- a/ncsi_util.cpp
+++ b/ncsi_util.cpp
@@ -19,17 +19,182 @@ namespace ncsi
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
-namespace internal
-{
-
constexpr auto DEFAULT_VALUE = -1;
constexpr auto NONE = 0;
+using CallBack = int(*)(struct nl_msg* msg, void* arg);
+
+namespace internal
+{
using nlMsgPtr = std::unique_ptr<nl_msg, decltype(&::nlmsg_free)>;
using nlSocketPtr = std::unique_ptr<nl_sock, decltype(&::nl_socket_free)>;
+CallBack infoCallBack = [](struct nl_msg* msg, void* arg)
+{
+ using namespace phosphor::network::ncsi;
+ auto nlh = nlmsg_hdr(msg);
+
+ struct nlattr* tb[NCSI_ATTR_MAX + 1] = { nullptr };
+ struct nla_policy ncsiPolicy[NCSI_ATTR_MAX + 1] =
+ {
+ { type: NLA_UNSPEC },
+ { type: NLA_U32 },
+ { type: NLA_NESTED },
+ { type: NLA_U32 },
+ { type: NLA_U32 },
+ };
+
+ struct nlattr* packagetb[NCSI_PKG_ATTR_MAX + 1] = { nullptr };
+ struct nla_policy packagePolicy[NCSI_PKG_ATTR_MAX + 1] =
+ {
+ { type: NLA_UNSPEC },
+ { type: NLA_NESTED },
+ { type: NLA_U32 },
+ { type: NLA_FLAG },
+ { type: NLA_NESTED },
+ };
+
+ struct nlattr* channeltb[NCSI_CHANNEL_ATTR_MAX + 1] = { nullptr };
+ struct nla_policy channelPolicy[NCSI_CHANNEL_ATTR_MAX + 1] =
+ {
+ { type: NLA_UNSPEC },
+ { type: NLA_NESTED },
+ { type: NLA_U32 },
+ { type: NLA_FLAG },
+ { type: NLA_NESTED },
+ { type: NLA_UNSPEC},
+ };
+
+ auto ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsiPolicy);
+ if (!tb[NCSI_ATTR_PACKAGE_LIST])
+ {
+ log<level::ERR>("No Packages");
+ return -1;
+ }
+
+ auto attrTgt = static_cast<nlattr*>(nla_data(tb[NCSI_ATTR_PACKAGE_LIST]));
+ if (!attrTgt)
+ {
+ log<level::ERR>("Package list attribute is null");
+ return -1;
+ }
+
+ auto rem = nla_len(tb[NCSI_ATTR_PACKAGE_LIST]);
+ nla_for_each_nested(attrTgt, tb[NCSI_ATTR_PACKAGE_LIST], rem)
+ {
+ ret = nla_parse_nested(packagetb, NCSI_PKG_ATTR_MAX, attrTgt,
+ packagePolicy);
+ if (ret < 0)
+ {
+ log<level::ERR>("Failed to parse package nested");
+ return -1;
+ }
+
+ if (packagetb[NCSI_PKG_ATTR_ID])
+ {
+ auto attrID = nla_get_u32(packagetb[NCSI_PKG_ATTR_ID]);
+ log<level::DEBUG>("Package has id",
+ entry("ID=%x", attrID));
+ }
+ else
+ {
+ log<level::DEBUG>("Package with no id\n");
+ }
+
+ if (packagetb[NCSI_PKG_ATTR_FORCED])
+ {
+ log<level::DEBUG>("This package is forced\n");
+ }
+
+ auto channelListTarget = static_cast<nlattr*>(
+ nla_data(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]));
+
+ auto channelrem = nla_len(packagetb[NCSI_PKG_ATTR_CHANNEL_LIST]);
+ nla_for_each_nested(channelListTarget,
+ packagetb[NCSI_PKG_ATTR_CHANNEL_LIST], channelrem)
+ {
+ ret = nla_parse_nested(channeltb, NCSI_CHANNEL_ATTR_MAX,
+ channelListTarget, channelPolicy);
+ if (ret < 0)
+ {
+ log<level::ERR>("Failed to parse channel nested");
+ return -1;
+ }
+
+ if (channeltb[NCSI_CHANNEL_ATTR_ID])
+ {
+ auto channel = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_ID]);
+ if (channeltb[NCSI_CHANNEL_ATTR_ACTIVE])
+ {
+ log<level::DEBUG>("Channel Active",
+ entry("CHANNEL=%x", channel));
+ }
+ else
+ {
+ log<level::DEBUG>("Channel not Active",
+ entry("CHANNEL=%x", channel));
+
+ }
+
+ if (channeltb[NCSI_CHANNEL_ATTR_FORCED])
+ {
+ log<level::DEBUG>("Channel is forced");
+ }
+
+ }
+ else
+ {
+ log<level::DEBUG>("Channel with no ID");
+ }
+ if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])
+ {
+ auto major = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MAJOR]);
+ log<level::DEBUG>("Channel Major Version",
+ entry("VERSION=%x", major));
+ }
+ if (channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR])
+ {
+ auto minor = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_VERSION_MINOR]);
+ log<level::DEBUG>("Channel Minor Version",
+ entry("VERSION=%x", minor));
+ }
+ if (channeltb[NCSI_CHANNEL_ATTR_VERSION_STR])
+ {
+ auto str = nla_get_string(channeltb[NCSI_CHANNEL_ATTR_VERSION_STR]);
+ log<level::DEBUG>("Channel Version Str",
+ entry("VERSION=%s", str));
+ }
+ if (channeltb[NCSI_CHANNEL_ATTR_LINK_STATE])
+ {
+ auto link = nla_get_u32(channeltb[NCSI_CHANNEL_ATTR_LINK_STATE]);
+ log<level::DEBUG>("Channel Link State",
+ entry("STATE=%d", link));
+ }
+ if (channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST])
+ {
+ log<level::DEBUG>("Active Vlan ids");
+ auto vids = channeltb[NCSI_CHANNEL_ATTR_VLAN_LIST];
+ auto vid = static_cast<nlattr*>(nla_data(vids));
+ auto len = nla_len(vids);
+ while (nla_ok(vid, len))
+ {
+ auto id = nla_get_u16(vid);
+ log<level::DEBUG>("VID",
+ entry("VID=%d", id));
+
+ vid = nla_next(vid, &len);
+ }
+ }
+
+ }
+
+ }
+ return (int)NL_SKIP;
+};
+
int applyCmd(int ifindex, int cmd, int package = DEFAULT_VALUE,
- int channel = DEFAULT_VALUE, int flags = NONE)
+ int channel = DEFAULT_VALUE, int flags = NONE,
+ CallBack function = nullptr)
{
nlSocketPtr socket(nl_socket_alloc(),&::nl_socket_free);
auto ret = genl_connect(socket.get());
@@ -94,6 +259,12 @@ int applyCmd(int ifindex, int cmd, int package = DEFAULT_VALUE,
return ret;
}
+ if (function)
+ {
+ // Add a callback function to the socket
+ nl_socket_modify_cb(socket.get(), NL_CB_VALID, NL_CB_CUSTOM,
+ function, nullptr);
+ }
ret = nl_send_auto(socket.get(), msg.get());
if (ret < 0)
@@ -126,6 +297,22 @@ int clearInterface(int ifindex)
ncsi_nl_commands::NCSI_CMD_CLEAR_INTERFACE);
}
+int getInfo(int ifindex, int package)
+{
+ if (package == DEFAULT_VALUE)
+ {
+ return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
+ package, DEFAULT_VALUE, NLM_F_DUMP,
+ internal::infoCallBack);
+ }
+ else
+ {
+ return internal::applyCmd(ifindex, ncsi_nl_commands::NCSI_CMD_PKG_INFO,
+ package, DEFAULT_VALUE, NONE,
+ internal::infoCallBack);
+ }
+}
+
}//namespace ncsi
}//namespace network
}//namespace phosphor
OpenPOWER on IntegriCloud