diff options
author | Petr Machata <petrm@nvidia.com> | 2022-04-22 10:30:58 +0200 |
---|---|---|
committer | David Ahern <dsahern@kernel.org> | 2022-04-27 20:12:42 -0600 |
commit | 0f1fd40cc9e8f4fdde18b67cd48ec2445ed7dc97 (patch) | |
tree | 6c1f5dcb28819b7558d7beb6b37b6d75d1288e13 | |
parent | 179030fa6bc714b12776aa5e0a905fadf7f3e402 (diff) | |
download | iproute2-0f1fd40cc9e8f4fdde18b67cd48ec2445ed7dc97.tar.gz |
ipstats: Add offload subgroup "l3_stats"
Add into the group "offload" a subgroup "l3_stats" for showing
L3 statistics.
For example:
# ip stats show dev swp2.200 group offload subgroup l3_stats
4212: swp2.200: group offload subgroup l3_stats on used on
RX: bytes packets errors dropped mcast
1920 21 1 0 0
TX: bytes packets errors dropped
756 9 0 0
# ip -j stats show dev swp2.200 group offload subgroup l3_stats | jq
[
{
"ifindex": 4212,
"ifname": "swp2.200",
"group": "offload",
"subgroup": "l3_stats",
"info": {
"request": true,
"used": true
},
"stats64": {
"rx": {
"bytes": 1920,
"packets": 21,
"errors": 1,
"dropped": 0,
"multicast": 0
},
"tx": {
"bytes": 756,
"packets": 9,
"errors": 0,
"dropped": 0
}
}
}
]
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r-- | ip/ipstats.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/ip/ipstats.c b/ip/ipstats.c index 4cdd5122a..29ca07318 100644 --- a/ip/ipstats.c +++ b/ip/ipstats.c @@ -164,6 +164,82 @@ static int ipstats_show_64(struct ipstats_stat_show_attrs *attrs, return 0; } +static void print_hw_stats64(FILE *fp, struct rtnl_hw_stats64 *s) +{ + unsigned int cols[] = { + strlen("*X: bytes"), + strlen("packets"), + strlen("errors"), + strlen("dropped"), + strlen("overrun"), + }; + + if (is_json_context()) { + /* RX stats */ + open_json_object("rx"); + print_u64(PRINT_JSON, "bytes", NULL, s->rx_bytes); + print_u64(PRINT_JSON, "packets", NULL, s->rx_packets); + print_u64(PRINT_JSON, "errors", NULL, s->rx_errors); + print_u64(PRINT_JSON, "dropped", NULL, s->rx_dropped); + print_u64(PRINT_JSON, "multicast", NULL, s->multicast); + close_json_object(); + + /* TX stats */ + open_json_object("tx"); + print_u64(PRINT_JSON, "bytes", NULL, s->tx_bytes); + print_u64(PRINT_JSON, "packets", NULL, s->tx_packets); + print_u64(PRINT_JSON, "errors", NULL, s->tx_errors); + print_u64(PRINT_JSON, "dropped", NULL, s->tx_dropped); + close_json_object(); + } else { + size_columns(cols, ARRAY_SIZE(cols), + s->rx_bytes, s->rx_packets, s->rx_errors, + s->rx_dropped, s->multicast); + size_columns(cols, ARRAY_SIZE(cols), + s->tx_bytes, s->tx_packets, s->tx_errors, + s->tx_dropped, 0); + + /* RX stats */ + fprintf(fp, " RX: %*s %*s %*s %*s %*s%s", + cols[0] - 4, "bytes", cols[1], "packets", + cols[2], "errors", cols[3], "dropped", + cols[4], "mcast", _SL_); + + fprintf(fp, " "); + print_num(fp, cols[0], s->rx_bytes); + print_num(fp, cols[1], s->rx_packets); + print_num(fp, cols[2], s->rx_errors); + print_num(fp, cols[3], s->rx_dropped); + print_num(fp, cols[4], s->multicast); + fprintf(fp, "%s", _SL_); + + /* TX stats */ + fprintf(fp, " TX: %*s %*s %*s %*s%s", + cols[0] - 4, "bytes", cols[1], "packets", + cols[2], "errors", cols[3], "dropped", _SL_); + + fprintf(fp, " "); + print_num(fp, cols[0], s->tx_bytes); + print_num(fp, cols[1], s->tx_packets); + print_num(fp, cols[2], s->tx_errors); + print_num(fp, cols[3], s->tx_dropped); + } +} + +static int ipstats_show_hw64(const struct rtattr *at) +{ + struct rtnl_hw_stats64 *stats; + + stats = IPSTATS_RTA_PAYLOAD(struct rtnl_hw_stats64, at); + if (stats == NULL) { + fprintf(stderr, "Error: attribute payload too short"); + return -EINVAL; + } + + print_hw_stats64(stdout, stats); + return 0; +} + enum ipstats_maybe_on_off { IPSTATS_MOO_OFF = -1, IPSTATS_MOO_INVALID, @@ -355,6 +431,57 @@ static int ipstats_show_hw_s_info(struct ipstats_stat_show_attrs *attrs, return __ipstats_show_hw_s_info(at); } +static int __ipstats_show_hw_stats(const struct rtattr *at_hwsi, + const struct rtattr *at_stats, + enum ipstats_hw_s_info_idx idx) +{ + int err = 0; + + if (at_hwsi != NULL) { + struct ipstats_hw_s_info hwsi = {}; + + err = ipstats_dissect_hw_s_info(at_hwsi, &hwsi); + if (err) + return err; + + open_json_object("info"); + __ipstats_show_hw_s_info_one(hwsi.infos[idx]); + close_json_object(); + + ipstats_fini_hw_s_info(&hwsi); + } + + if (at_stats != NULL) { + print_nl(); + open_json_object("stats64"); + err = ipstats_show_hw64(at_stats); + close_json_object(); + } + + return err; +} + +static int ipstats_show_hw_stats(struct ipstats_stat_show_attrs *attrs, + unsigned int group, + unsigned int hw_s_info, + unsigned int hw_stats, + enum ipstats_hw_s_info_idx idx) +{ + const struct rtattr *at_stats; + const struct rtattr *at_hwsi; + int err = 0; + + at_hwsi = ipstats_stat_show_get_attr(attrs, group, hw_s_info, &err); + if (at_hwsi == NULL) + return err; + + at_stats = ipstats_stat_show_get_attr(attrs, group, hw_stats, &err); + if (at_stats == NULL && err != 0) + return err; + + return __ipstats_show_hw_stats(at_hwsi, at_stats, idx); +} + static void ipstats_stat_desc_pack_cpu_hit(struct ipstats_stat_dump_filters *filters, const struct ipstats_stat_desc *desc) @@ -405,9 +532,40 @@ static const struct ipstats_stat_desc ipstats_stat_desc_offload_hw_s_info = { .show = &ipstats_stat_desc_show_hw_stats_info, }; +static void +ipstats_stat_desc_pack_l3_stats(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_L3_STATS); + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO); +} + +static int +ipstats_stat_desc_show_l3_stats(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + return ipstats_show_hw_stats(attrs, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO, + IFLA_OFFLOAD_XSTATS_L3_STATS, + IPSTATS_HW_S_INFO_IDX_L3_STATS); +} + +static const struct ipstats_stat_desc ipstats_stat_desc_offload_l3_stats = { + .name = "l3_stats", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_l3_stats, + .show = &ipstats_stat_desc_show_l3_stats, +}; + static const struct ipstats_stat_desc *ipstats_stat_desc_offload_subs[] = { &ipstats_stat_desc_offload_cpu_hit, &ipstats_stat_desc_offload_hw_s_info, + &ipstats_stat_desc_offload_l3_stats, }; static const struct ipstats_stat_desc ipstats_stat_desc_offload_group = { |