Files
s390-tools/zconf/chp/chpstat/column.c
Peter Oberparleiter de18a72249 chpstat: Add data bandwidth utilization column
Add column 'UTIL DATA' that indicates the percentage of channel-path
data bandwidth currently in use. Since channel-paths are bidirectional,
this column represents the maximum of read or write bandwidth
utilization.

Also use this new column in place of 'UTIL BUS' for CMG 4 and 5 default
views since the bus utilization no longer provides a relevant value for
DPU-based channel-path types.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-11-29 15:52:24 +01:00

484 lines
8.0 KiB
C

/*
* Registry for supported table columns
*
* Copyright IBM Corp. 2024
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include <stdbool.h>
#include "column.h"
#include "lib/util_base.h"
#include "lib/util_libc.h"
/*
* Use group header for adjacent columns of the same type to improve
* readability.
*
* Single header: UTIL Group header: UTILIZATION
* PART PART TOTAL
*/
#define HDR1_CHP_SINGLE ""
#define HDR1_CHP_GROUP "CHANNEL-PATH"
#define HDR1_UTIL_SINGLE "UTIL"
#define HDR1_UTIL_GROUP "UTILIZATION(%)"
#define HDR1_READ_SINGLE "READ"
#define HDR1_READ_GROUP "READ"
#define HDR1_WRITE_SINGLE "WRITE"
#define HDR1_WRITE_GROUP "WRITE"
#define HDR1_FICON_SINGLE "FICON"
#define HDR1_FICON_GROUP "FICON-OPS"
#define HDR1_HPF_SINGLE "HPF"
#define HDR1_HPF_GROUP "HPF-OPS"
#define HDR1_MSGR_SINGLE "RATE"
#define HDR1_MSGR_GROUP "MSG-RATE"
#define HDR1_MSGSZ_SINGLE "SIZE"
#define HDR1_MSGSZ_GROUP "MSG-SIZE"
#define HDR1_MSG_RCVF_SINGLE "RFAIL"
#define HDR1_MSG_RCVF_GROUP "RECEIVE-FAIL"
#define HDR1_DPU_UTIL_SINGLE "DPU"
#define HDR1_DPU_UTIL_GROUP "DPU UTILIZATION(%)"
static struct column_t columns[] = {
{
COL_CHPID,
"chpid",
COL_OTHER,
"Channel-path ID",
"ID",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_TYPE,
"type",
COL_OTHER,
"Channel-path type",
"TYP",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_CMG,
"cmg",
COL_OTHER,
"Channel-measurement group",
"CMG",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_SPEED,
"speed",
COL_OTHER,
"Operational speed",
"SPEED",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_SHARED,
"shared",
COL_OTHER,
"Shared channel-path indicator",
"SHR",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_INTERVAL,
"interval",
COL_OTHER,
"Cumulated statistics update interval",
"INT",
HDR1_CHP_SINGLE,
HDR1_CHP_GROUP,
0,
},
{
COL_UTIL_PART,
"util_part",
COL_PERCENT,
"Partition channel-path utilization in %",
"PART",
HDR1_UTIL_SINGLE,
HDR1_UTIL_GROUP,
0,
},
{
COL_UTIL_TOTAL,
"util_total",
COL_PERCENT,
"Total channel-path utilization in %",
"TOTAL",
HDR1_UTIL_SINGLE,
HDR1_UTIL_GROUP,
0,
},
{
COL_UTIL_BUS,
"util_bus",
COL_PERCENT,
"Bus utilization in %",
"BUS",
HDR1_UTIL_SINGLE,
HDR1_UTIL_GROUP,
0,
},
{
COL_UTIL_DATA,
"util_data",
COL_PERCENT,
"Data bandwidth utilization in %",
"DATA",
HDR1_UTIL_SINGLE,
HDR1_UTIL_GROUP,
0,
},
{
COL_READ_PART,
"read_part",
COL_BPS,
"Partition read throughput in B/s",
"PART",
HDR1_READ_SINGLE,
HDR1_READ_GROUP,
0,
},
{
COL_READ_TOTAL,
"read_total",
COL_BPS,
"Total read throughput in B/s",
"TOTAL",
HDR1_READ_SINGLE,
HDR1_READ_GROUP,
0,
},
{
COL_WRITE_PART,
"write_part",
COL_BPS,
"Partition write throughput in B/s",
"PART",
HDR1_WRITE_SINGLE,
HDR1_WRITE_GROUP,
0,
},
{
COL_WRITE_TOTAL,
"write_total",
COL_BPS,
"Total write throughput in B/s",
"TOTAL",
HDR1_WRITE_SINGLE,
HDR1_WRITE_GROUP,
0,
},
{
COL_FICON_RATE,
"ficon_rate",
COL_NUMBER,
"FICON operations per second",
"RATE",
HDR1_FICON_SINGLE,
HDR1_FICON_GROUP,
0,
},
{
COL_FICON_ACTIVE,
"ficon_active",
COL_NUMBER,
"Avg. concurrently active FICON operations",
"ACTV",
HDR1_FICON_SINGLE,
HDR1_FICON_GROUP,
0,
},
{
COL_FICON_DEFER,
"ficon_defer",
COL_NUMBER,
"Deferred FICON operations per second",
"DEFER",
HDR1_FICON_SINGLE,
HDR1_FICON_GROUP,
0,
},
{
COL_HPF_RATE,
"hpf_rate",
COL_NUMBER,
"HPF operations per second",
"RATE",
HDR1_HPF_SINGLE,
HDR1_HPF_GROUP,
0,
},
{
COL_HPF_ACTIVE,
"hpf_active",
COL_NUMBER,
"Avg. concurrently active HPF operations",
"ACTV",
HDR1_HPF_SINGLE,
HDR1_HPF_GROUP,
0,
},
{
COL_HPF_DEFER,
"hpf_defer",
COL_NUMBER,
"Deferred HPF operations per second",
"DEFER",
HDR1_HPF_SINGLE,
HDR1_HPF_GROUP,
0,
},
{
COL_MSG_RATE_PART,
"msg_rate_part",
COL_NUMBER,
"Partition message send rate per second",
"PART",
HDR1_MSGR_SINGLE,
HDR1_MSGR_GROUP,
0,
},
{
COL_MSG_RATE_TOTAL,
"msg_rate_total",
COL_NUMBER,
"Total message send rate per second",
"TOTAL",
HDR1_MSGR_SINGLE,
HDR1_MSGR_GROUP,
0,
},
{
COL_MSG_SIZE_PART,
"msg_size_part",
COL_NUMBER,
"Partition avg. send message size",
"PART",
HDR1_MSGSZ_SINGLE,
HDR1_MSGSZ_GROUP,
0,
},
{
COL_MSG_SIZE_TOTAL,
"msg_size_total",
COL_NUMBER,
"Total avg. send message size",
"TOTAL",
HDR1_MSGSZ_SINGLE,
HDR1_MSGSZ_GROUP,
0,
},
{
COL_SEND_FAIL_PART,
"send_fail_part",
COL_NUMBER,
"Partition message send fail rate per second",
"PART",
"SNDFAIL",
"SNDFAIL",
0,
},
{
COL_RCV_FAIL_PART,
"rcv_fail_part",
COL_NUMBER,
"Partition message receive fail rate per second",
"PART",
HDR1_MSG_RCVF_SINGLE,
HDR1_MSG_RCVF_GROUP,
0,
},
{
COL_RCV_FAIL_TOTAL,
"rcv_fail_total",
COL_NUMBER,
"Total message receive fail rate per second",
"TOTAL",
HDR1_MSG_RCVF_SINGLE,
HDR1_MSG_RCVF_GROUP,
0,
},
{
COL_DPU_ID,
"dpu_id",
COL_OTHER,
"DPU ID associated with channel-path",
"ID",
HDR1_DPU_UTIL_SINGLE,
HDR1_DPU_UTIL_GROUP,
0,
},
{
COL_DPU_UTIL,
"dpu_util",
COL_PERCENT,
"Full DPU utilization in %",
"FULL",
HDR1_DPU_UTIL_SINGLE,
HDR1_DPU_UTIL_GROUP,
0,
},
{
COL_DPU_UTIL_PART,
"dpu_util_part",
COL_PERCENT,
"Partition channel-path DPU utilization in %",
"PART",
HDR1_DPU_UTIL_SINGLE,
HDR1_DPU_UTIL_GROUP,
0,
},
{
COL_DPU_UTIL_TOTAL,
"dpu_util_total",
COL_PERCENT,
"Total channel-path DPU utilization in %",
"TOTAL",
HDR1_DPU_UTIL_SINGLE,
HDR1_DPU_UTIL_GROUP,
0,
},
};
/* Columns selected by default. */
static const int default_columns[] = {
COL_CHPID,
COL_TYPE,
COL_CMG,
COL_SHARED,
COL_SPEED,
COL_UTIL_PART,
COL_UTIL_TOTAL,
COL_UTIL_BUS,
COL_DPU_ID,
COL_READ_PART,
COL_READ_TOTAL,
COL_WRITE_PART,
COL_WRITE_TOTAL,
/* End of list. */
COL_END
};
static struct column_t **selected_cols;
static unsigned int num_selected_cols;
static bool hdr_updated;
struct column_t *column_get_by_index(unsigned int i, bool selected)
{
if (selected)
return i < num_selected_cols ? selected_cols[i] : NULL;
return i < ARRAY_SIZE(columns) ? &columns[i] : NULL;
}
/*
* Retrieve column object by @name or %NULL if column does not exist.
*/
struct column_t *column_get_by_name(const char *name)
{
struct column_t *col;
column_for_each(col) {
if (strcasecmp(col->name, name) == 0)
return col;
}
return NULL;
}
/*
* Add the specified column to the list of selected columns. Discard duplicate
* selections of the same column.
*/
void column_select(struct column_t *col)
{
struct column_t *c;
/* Silently filter out double selection of columns to prevent problems
* with non-unique util_rec name fields. */
column_for_each_selected(c) {
if (c == col)
return;
}
util_add_array(&selected_cols, &num_selected_cols, col);
}
void column_select_id_list(const int *ids)
{
struct column_t *col;
int i;
for (i = 0; ids[i] != COL_END; i++) {
column_for_each(col) {
if (col->id == ids[i]) {
column_select(col);
break;
}
}
}
}
void column_select_default(void)
{
column_select_id_list(default_columns);
}
void column_select_all(void)
{
struct column_t *col;
column_for_each(col)
column_select(col);
}
void column_update_bps_suffix(bool auto_scale, char suffix_char)
{
struct column_t *col;
char *str;
if (auto_scale)
util_asprintf(&str, "(B/s)");
else if (suffix_char)
util_asprintf(&str, "(%ciB/s)", suffix_char);
else
str = util_strdup("(*)");
column_for_each(col) {
if (col->unit != COL_BPS) {
col->hdr1_group = util_strdup(col->hdr1_group);
continue;
}
util_asprintf(&col->hdr1_group, "%s%s", col->hdr1_group, str);
}
free(str);
hdr_updated = true;
}
void column_exit(void)
{
struct column_t *col;
if (hdr_updated) {
column_for_each(col)
free(col->hdr1_group);
}
free(selected_cols);
}