Adds the same functionality of the ETHTOOL_{G,S}FP commands, now via
the ETHTOOL_MSG_PREEMPT_{GET,SET} netlink messages.

Signed-off-by: Vinicius Costa Gomes <vinicius.go...@intel.com>
---
 Makefile.am            |   2 +-
 ethtool.c              |   2 +
 netlink/desc-ethtool.c |  13 ++++
 netlink/extapi.h       |   4 ++
 netlink/preempt.c      | 148 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 netlink/preempt.c

diff --git a/Makefile.am b/Makefile.am
index 0f8465f..3b88533 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,7 +32,7 @@ ethtool_SOURCES += \
                  netlink/settings.c netlink/parser.c netlink/parser.h \
                  netlink/permaddr.c netlink/prettymsg.c netlink/prettymsg.h \
                  netlink/desc-ethtool.c netlink/desc-genlctrl.c \
-                 netlink/desc-rtnl.c \
+                 netlink/desc-rtnl.c netlink/preempt.c \
                  uapi/linux/ethtool_netlink.h \
                  uapi/linux/netlink.h uapi/linux/genetlink.h \
                  uapi/linux/rtnetlink.h uapi/linux/if_link.h
diff --git a/ethtool.c b/ethtool.c
index 4c69d1c..3acdd54 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5587,11 +5587,13 @@ static const struct option args[] = {
        {
                .opts   = "--show-frame-preemption",
                .func   = do_get_preempt,
+               .nlfunc = nl_get_preempt,
                .help   = "Show Frame Preemption settings",
        },
        {
                .opts   = "--set-frame-preemption",
                .func   = do_set_preempt,
+               .nlfunc = nl_set_preempt,
                .help   = "Set Frame Preemption settings",
                .xhelp  = "             [ fp on|off ]\n"
                          "             [ preemptible-queues-mask %x ]\n"
diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c
index 76c6f13..f82afd2 100644
--- a/netlink/desc-ethtool.c
+++ b/netlink/desc-ethtool.c
@@ -106,6 +106,17 @@ static const struct pretty_nla_desc __wol_desc[] = {
        NLATTR_DESC_BINARY(ETHTOOL_A_WOL_SOPASS),
 };
 
+static const struct pretty_nla_desc __preempt_desc[] = {
+       NLATTR_DESC_INVALID(ETHTOOL_A_PREEMPT_UNSPEC),
+       NLATTR_DESC_NESTED(ETHTOOL_A_PREEMPT_HEADER, header),
+       NLATTR_DESC_U8(ETHTOOL_A_PREEMPT_SUPPORTED),
+       NLATTR_DESC_U8(ETHTOOL_A_PREEMPT_ACTIVE),
+       NLATTR_DESC_U32(ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED),
+       NLATTR_DESC_U32(ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE),
+       NLATTR_DESC_U32(ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE),
+       NLATTR_DESC_BINARY(ETHTOOL_A_WOL_SOPASS),
+};
+
 const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
        NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE),
        NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset),
@@ -118,6 +129,8 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = {
        NLMSG_DESC(ETHTOOL_MSG_DEBUG_SET, debug),
        NLMSG_DESC(ETHTOOL_MSG_WOL_GET, wol),
        NLMSG_DESC(ETHTOOL_MSG_WOL_SET, wol),
+       NLMSG_DESC(ETHTOOL_MSG_PREEMPT_GET, preempt),
+       NLMSG_DESC(ETHTOOL_MSG_PREEMPT_SET, preempt),
 };
 
 const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc);
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 9484b4c..2436f70 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -21,6 +21,8 @@ int nl_gset(struct cmd_context *ctx);
 int nl_sset(struct cmd_context *ctx);
 int nl_permaddr(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
+int nl_get_preempt(struct cmd_context *ctx);
+int nl_set_preempt(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
 
@@ -44,6 +46,8 @@ static inline void nl_monitor_usage(void)
 #define nl_gset                        NULL
 #define nl_sset                        NULL
 #define nl_permaddr            NULL
+#define nl_get_preempt         NULL
+#define nl_set_preempt         NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/preempt.c b/netlink/preempt.c
new file mode 100644
index 0000000..976ae39
--- /dev/null
+++ b/netlink/preempt.c
@@ -0,0 +1,148 @@
+/*
+ * preempt.c - netlink implementation of frame preemption settings
+ *
+ * Implementation of "ethtool --{show,set}-frame-preemption <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+#include "parser.h"
+
+/* PREEMPT_GET */
+
+static int preempt_get_prep_request(struct nl_socket *nlsk)
+{
+       int ret;
+
+       ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PREEMPT_GET,
+                                     ETHTOOL_A_PREEMPT_HEADER, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+int preempt_get_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+       const struct nlattr *tb[ETHTOOL_A_PREEMPT_MAX + 1] = {};
+       DECLARE_ATTR_TB_INFO(tb);
+       struct nl_context *nlctx = data;
+       int ret;
+
+       if (nlctx->is_dump || nlctx->is_monitor)
+               nlctx->no_banner = false;
+
+       ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+       if (ret < 0)
+               return ret;
+
+       nlctx->devname = get_dev_name(tb[ETHTOOL_A_PREEMPT_HEADER]);
+       if (!dev_ok(nlctx))
+               return MNL_CB_OK;
+
+       printf("Frame preemption settings for %s:\n", nlctx->devname);
+
+       if (tb[ETHTOOL_A_PREEMPT_SUPPORTED]) {
+               int supported = mnl_attr_get_u8(
+                       tb[ETHTOOL_A_PREEMPT_SUPPORTED]);
+
+               printf("\tsupport: %s\n",
+                      supported ? "supported" : "not supported");
+       }
+       if (tb[ETHTOOL_A_PREEMPT_ACTIVE]) {
+               int active = mnl_attr_get_u8(tb[ETHTOOL_A_PREEMPT_ACTIVE]);
+
+               printf("\tactive: %s\n", active ? "active" : "not active");
+       }
+       if (tb[ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED]) {
+               uint32_t queues = mnl_attr_get_u32(
+                       tb[ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED]);
+
+               printf("\tsupported queues: %#x\n", queues);
+
+       }
+       if (tb[ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE]) {
+               uint32_t queues = mnl_attr_get_u32(
+                       tb[ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE]);
+
+               printf("\tsupported queues: %#x\n", queues);
+
+       }
+       if (tb[ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE]) {
+               uint32_t min_frag_size = mnl_attr_get_u32(
+                       tb[ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE]);
+
+               printf("\tminimum fragment size: %d\n", min_frag_size);
+       }
+       return MNL_CB_OK;
+}
+
+int nl_get_preempt(struct cmd_context *ctx)
+{
+       struct nl_context *nlctx = ctx->nlctx;
+       struct nl_socket *nlsk = nlctx->ethnl_socket;
+       int ret;
+
+       ret = preempt_get_prep_request(nlsk);
+       if (ret < 0)
+               return ret;
+       return nlsock_send_get_request(nlsk, preempt_get_reply_cb);
+}
+
+static const struct lookup_entry_u8 fp_values[] = {
+       { .arg = "off",         .val = 0 },
+       { .arg = "on",          .val = 1 },
+       {}
+};
+
+static const struct param_parser set_preempt_params[] = {
+       {
+               .arg            = "fp",
+               .group          = ETHTOOL_MSG_PREEMPT_SET,
+               .type           = ETHTOOL_A_PREEMPT_ACTIVE,
+               .handler        = nl_parse_lookup_u8,
+               .handler_data   = fp_values,
+               .min_argc       = 1,
+       },
+       {
+               .arg            = "preemptible-queues-mask",
+               .group          = ETHTOOL_MSG_PREEMPT_SET,
+               .type           = ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE,
+               .handler        = nl_parse_direct_u32,
+               .min_argc       = 1,
+       },
+       {
+               .arg            = "min-frag-size",
+               .group          = ETHTOOL_MSG_PREEMPT_SET,
+               .type           = ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE,
+               .handler        = nl_parse_direct_u32,
+               .min_argc       = 1,
+       },
+       {}
+};
+
+int nl_set_preempt(struct cmd_context *ctx)
+{
+       struct nl_context *nlctx = ctx->nlctx;
+       int ret;
+
+       nlctx->cmd = "--set-frame-preemption";
+       nlctx->argp = ctx->argp;
+       nlctx->argc = ctx->argc;
+       nlctx->devname = ctx->devname;
+
+       ret = nl_parser(nlctx, set_preempt_params, NULL, PARSER_GROUP_MSG);
+       if (ret < 0)
+               return 1;
+
+       if (ret == 0)
+               return 0;
+       return nlctx->exit_code ?: 75;
+}
-- 
2.26.2

Reply via email to