diff options
Diffstat (limited to 'ncsi_util.cpp')
-rw-r--r-- | ncsi_util.cpp | 195 |
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 |