diff options
author | Ratan Gupta <ratagupt@in.ibm.com> | 2018-03-23 00:25:54 +0530 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2018-04-04 16:12:22 +0000 |
commit | aac603e46d8f9241eac911e28b3ac349ed425efc (patch) | |
tree | 3a12ecec16eeb82cdcba7f48cae4f53a56581787 | |
parent | bbe4579661b102fa0a5994c9b6a9ecb98add6954 (diff) | |
download | phosphor-networkd-aac603e46d8f9241eac911e28b3ac349ed425efc.tar.gz phosphor-networkd-aac603e46d8f9241eac911e28b3ac349ed425efc.zip |
ncsi: implement the getinfo function
This function is used to dump all the info
of the package and the channels underlying
the package.
This function talks with the NCSI driver over
netlink messages.
Change-Id: Ie0aa8924049a6d3b32426627e025f653f84cfbe9
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
-rw-r--r-- | ncsi_util.cpp | 195 | ||||
-rw-r--r-- | ncsi_util.hpp | 9 |
2 files changed, 200 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 diff --git a/ncsi_util.hpp b/ncsi_util.hpp index c519cb4..570152b 100644 --- a/ncsi_util.hpp +++ b/ncsi_util.hpp @@ -27,6 +27,15 @@ int setChannel(int ifindex, int package, int channel); */ int clearInterface(int ifindex); +/* @brief This function is used to dump all the info + * of the package and the channels underlying + * the package. + * @param[in] ifindex - Interface Index. + * @param[in] package - NCSI Package. + * @returns 0 on success and negative value for failure. + */ +int getInfo(int ifindex, int package); + }//namespace ncsi }//namespace network }//namespace phosphor |