From: Kan Liang <kan.li...@intel.com>

Get all masked queues' coalesce from kernel and dump them one by one.

Example:

 $ sudo ./ethtool --set-perqueue-command eth5 queue_mask 0x11
   --show-coalesce
 Queue: 0
 Adaptive RX: off  TX: off
 stats-block-usecs: 0
 sample-interval: 0
 pkt-rate-low: 0
 pkt-rate-high: 0

 rx-usecs: 222
 rx-frames: 0
 rx-usecs-irq: 0
 rx-frames-irq: 256

 tx-usecs: 222
 tx-frames: 0
 tx-usecs-irq: 0
 tx-frames-irq: 256

 rx-usecs-low: 0
 rx-frame-low: 0
 tx-usecs-low: 0
 tx-frame-low: 0

 rx-usecs-high: 0
 rx-frame-high: 0
 tx-usecs-high: 0
 tx-frame-high: 0

 Queue: 4
 Adaptive RX: off  TX: off
 stats-block-usecs: 0
 sample-interval: 0
 pkt-rate-low: 0
 pkt-rate-high: 0

 rx-usecs: 222
 rx-frames: 0
 rx-usecs-irq: 0
 rx-frames-irq: 256

 tx-usecs: 222
 tx-frames: 0
 tx-usecs-irq: 0
 tx-frames-irq: 256

 rx-usecs-low: 0
 rx-frame-low: 0
 tx-usecs-low: 0
 tx-frame-low: 0

 rx-usecs-high: 0
 rx-frame-high: 0
 tx-usecs-high: 0
 tx-frame-high: 0

Signed-off-by: Kan Liang <kan.li...@intel.com>
---
 ethtool.8.in |  2 +-
 ethtool.c    | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/ethtool.8.in b/ethtool.8.in
index 26d01cb..210ec8c 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -937,7 +937,7 @@ Sets the specific queues which the sub command is applied 
to.
 If queue_mask is not set, the sub command will be applied to all queues.
 .TP
 .B sub_command
-Sets the sub command.
+Sets the sub command. The supported sub commands include --show-coalesce.
 .RE
 .SH BUGS
 Not supported (in part or whole) on all network drivers.
diff --git a/ethtool.c b/ethtool.c
index ba741f0..a966bf8 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1219,6 +1219,29 @@ static int dump_coalesce(const struct ethtool_coalesce 
*ecoal)
        return 0;
 }
 
+void dump_per_queue_coalesce(struct ethtool_per_queue_op *per_queue_opt,
+                            __u32 *queue_mask)
+{
+       char *addr;
+       int i;
+
+       addr = (char *)per_queue_opt + sizeof(*per_queue_opt);
+       for (i = 0; i < __KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32); i++) {
+               int queue = i * 32;
+               __u32 mask = queue_mask[i];
+
+               while (mask > 0) {
+                       if (mask & 0x1) {
+                               fprintf(stdout, "Queue: %d\n", queue);
+                               dump_coalesce((struct ethtool_coalesce *)addr);
+                               addr += sizeof(struct ethtool_coalesce);
+                       }
+                       mask = mask >> 1;
+                       queue++;
+               }
+       }
+}
+
 struct feature_state {
        u32 off_flags;
        struct ethtool_gfeatures features;
@@ -4198,7 +4221,8 @@ static const struct option {
          "             [ advertise %x ]\n"
          "             [ tx-lpi on|off ]\n"
          "             [ tx-timer %d ]\n"},
-       { "--set-perqueue-command", 1, do_perqueue, "Set per queue command",
+       { "--set-perqueue-command", 1, do_perqueue, "Set per queue command. "
+         "The supported sub commands include --show-coalesce",
          "             [queue_mask %x] SUB_COMMAND\n"},
        { "-h|--help", 0, show_usage, "Show this help" },
        { "--version", 0, do_version, "Show version number" },
@@ -4302,8 +4326,31 @@ static int find_max_num_queues(struct cmd_context *ctx)
        return MAX(MAX(echannels.rx_count, echannels.tx_count), 
echannels.combined_count);
 }
 
+static struct ethtool_per_queue_op *
+get_per_queue_coalesce(struct cmd_context *ctx,
+                      __u32 *queue_mask, int n_queues)
+{
+       struct ethtool_per_queue_op *per_queue_opt;
+
+       per_queue_opt = malloc(sizeof(*per_queue_opt) + n_queues * 
sizeof(struct ethtool_coalesce));
+       if (!per_queue_opt)
+               return NULL;
+
+       memcpy(per_queue_opt->queue_mask, queue_mask, 
__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32) * sizeof(__u32));
+       per_queue_opt->cmd = ETHTOOL_PERQUEUE;
+       per_queue_opt->sub_command = ETHTOOL_GCOALESCE;
+       if (send_ioctl(ctx, per_queue_opt)) {
+               free(per_queue_opt);
+               perror("Cannot get device per queue parameters");
+               return NULL;
+       }
+
+       return per_queue_opt;
+}
+
 static int do_perqueue(struct cmd_context *ctx)
 {
+       struct ethtool_per_queue_op *per_queue_opt;
        __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)] = {0};
        int i, n_queues = 0;
 
@@ -4342,7 +4389,18 @@ static int do_perqueue(struct cmd_context *ctx)
        if (i < 0)
                exit_bad_args();
 
-       /* no sub_command support yet */
+       if (strstr(args[i].opts, "--show-coalesce") != NULL) {
+               per_queue_opt = get_per_queue_coalesce(ctx, queue_mask, 
n_queues);
+               if (per_queue_opt == NULL) {
+                       perror("Cannot get device per queue parameters");
+                       return -EFAULT;
+               }
+               dump_per_queue_coalesce(per_queue_opt, queue_mask);
+               free(per_queue_opt);
+       } else {
+               perror("The subcommand is not supported yet");
+               return -EOPNOTSUPP;
+       }
 
        return 0;
 }
-- 
2.5.0

Reply via email to