Add a function using ethtool netlink to check whether a PHC is a virtual
clock of an interface.

Signed-off-by: Miroslav Lichvar <mlich...@redhat.com>
Acked-by: Hangbin Liu <liuhang...@gmail.com>
---
 rtnl.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rtnl.h |  9 +++++++
 2 files changed, 92 insertions(+)

diff --git a/rtnl.c b/rtnl.c
index f8bdbe6..0039d07 100644
--- a/rtnl.c
+++ b/rtnl.c
@@ -19,6 +19,7 @@
 #include <asm/types.h>
 #include <sys/socket.h> /* Must come before linux/netlink.h on some systems. */
 #include <linux/netlink.h>
+#include <linux/ethtool_netlink.h>
 #include <linux/rtnetlink.h>
 #include <linux/genetlink.h>
 #include <linux/if_team.h>
@@ -465,3 +466,85 @@ no_info:
        nl_close(fd);
        return index;
 }
+
+static int rtnl_search_vclocks(struct rtattr *attr, int phc_index)
+{
+       int i, len = RTA_PAYLOAD(attr);
+
+       for (i = 0; i < len / sizeof (__s32); i++) {
+               if (((__s32 *)RTA_DATA(attr))[i] == phc_index)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int rtnl_iface_has_vclock(const char *device, int phc_index)
+{
+       struct rtattr *tb[ETHTOOL_A_PHC_VCLOCKS_MAX + 1];
+       int index, fd, gf_id, len, ret = 0;
+       struct genlmsghdr *gnlh;
+       struct nlmsghdr *nlh;
+       char msg[BUF_SIZE];
+       struct {
+               struct nlattr attr;
+               uint32_t index;
+       } req;
+
+       index = if_nametoindex(device);
+
+       fd = nl_open(NETLINK_GENERIC);
+       if (fd < 0)
+               return fd;
+
+       gf_id = genl_get_family_id(fd, ETHTOOL_GENL_NAME);
+       if (gf_id < 0) {
+               pr_err("get genl family failed");
+               goto no_info;
+       }
+
+       req.attr.nla_len = sizeof(req);
+       req.attr.nla_type = ETHTOOL_A_HEADER_DEV_INDEX;
+       req.index = index;
+
+       len = genl_send_msg(fd, gf_id, ETHTOOL_MSG_PHC_VCLOCKS_GET,
+                           ETHTOOL_GENL_VERSION,
+                           NLA_F_NESTED | ETHTOOL_A_PHC_VCLOCKS_HEADER, 
+                           &req, sizeof(req));
+
+       if (len < 0) {
+               pr_err("send vclock request failed: %m");
+               goto no_info;
+       }
+
+       len = recv(fd, msg, sizeof(msg), 0);
+       if (len < 0) {
+               pr_err("recv vclock failed: %m");
+               goto no_info;
+       }
+
+       for (nlh = (struct nlmsghdr *) msg; NLMSG_OK(nlh, len);
+            nlh = NLMSG_NEXT(nlh, len)) {
+               if (nlh->nlmsg_type != gf_id)
+                       continue;
+
+               gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh);
+               if (gnlh->cmd != ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY)
+                       continue;
+
+               if (rtnl_rtattr_parse(tb, ETHTOOL_A_PHC_VCLOCKS_MAX,
+                                     (struct rtattr *) GENLMSG_DATA(msg),
+                                     NLMSG_PAYLOAD(nlh, GENL_HDRLEN)))
+                       continue;
+
+               if (tb[ETHTOOL_A_PHC_VCLOCKS_INDEX]) {
+                       ret = 
rtnl_search_vclocks(tb[ETHTOOL_A_PHC_VCLOCKS_INDEX],
+                                                 phc_index);
+                       break;
+               }
+       }
+
+no_info:
+       nl_close(fd);
+       return ret;
+}
diff --git a/rtnl.h b/rtnl.h
index 8fef4a9..96fee29 100644
--- a/rtnl.h
+++ b/rtnl.h
@@ -59,6 +59,15 @@ int rtnl_link_query(int fd, const char *device);
  */
 int rtnl_link_status(int fd, const char *device, rtnl_callback cb, void *ctx);
 
+/**
+ * Check if the PHC is a virtual clock of the interface (i.e. sockets bound to
+ * the interface also need to be bound to the clock).
+ * @param device    Name of the interface.
+ * @param phc_index Index of the clock to check.
+ * @return          1 if true, otherwise 0.
+ */
+int rtnl_iface_has_vclock(const char *device, int phc_index);
+
 /**
  * Open a RT netlink socket for monitoring link state.
  * @return    A valid socket, or -1 on error.
-- 
2.34.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to