summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRatan Gupta <ratagupt@in.ibm.com>2018-03-23 00:25:54 +0530
committerBrad Bishop <bradleyb@fuzziesquirrel.com>2018-04-04 16:12:22 +0000
commitaac603e46d8f9241eac911e28b3ac349ed425efc (patch)
tree3a12ecec16eeb82cdcba7f48cae4f53a56581787
parentbbe4579661b102fa0a5994c9b6a9ecb98add6954 (diff)
downloadphosphor-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.cpp195
-rw-r--r--ncsi_util.hpp9
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
OpenPOWER on IntegriCloud