From: Nikolay Aleksandrov Date: Sun, 8 May 2022 04:53:40 +0000 (+0000) Subject: bridge: vni: add support for stats dumping X-Git-Tag: v5.19.0~24^2~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40b50f153c52e14b1848c74fd09ffc9e51b75c8a;p=thirdparty%2Fiproute2.git bridge: vni: add support for stats dumping Add support for "-s" option which causes bridge vni to dump per-vni statistics. Note that it disables vni range compression. Example: $ bridge -s vni | more dev vni group/remote vxlan0 1024 239.1.1.1 RX: bytes 0 pkts 0 drops 0 errors 0 TX: bytes 0 pkts 0 drops 0 errors 0 1025 239.1.1.1 RX: bytes 0 pkts 0 drops 0 errors 0 TX: bytes 0 pkts 0 drops 0 errors 0 Signed-off-by: Nikolay Aleksandrov Signed-off-by: Roopa Prabhu Signed-off-by: David Ahern --- diff --git a/bridge/vni.c b/bridge/vni.c index 79dff005a..a0c2792c7 100644 --- a/bridge/vni.c +++ b/bridge/vni.c @@ -186,6 +186,59 @@ static void print_range(const char *name, __u32 start, __u32 id) } +static void print_vnifilter_entry_stats(struct rtattr *stats_attr) +{ + struct rtattr *stb[VNIFILTER_ENTRY_STATS_MAX+1]; + __u64 stat; + + open_json_object("stats"); + parse_rtattr_flags(stb, VNIFILTER_ENTRY_STATS_MAX, RTA_DATA(stats_attr), + RTA_PAYLOAD(stats_attr), NLA_F_NESTED); + + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + print_string(PRINT_FP, NULL, "RX: ", ""); + + if (stb[VNIFILTER_ENTRY_STATS_RX_BYTES]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_RX_BYTES]); + print_lluint(PRINT_ANY, "rx_bytes", "bytes %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_RX_PKTS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_RX_PKTS]); + print_lluint(PRINT_ANY, "rx_pkts", "pkts %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_RX_DROPS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_RX_DROPS]); + print_lluint(PRINT_ANY, "rx_drops", "drops %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_RX_ERRORS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_RX_ERRORS]); + print_lluint(PRINT_ANY, "rx_errors", "errors %llu ", stat); + } + + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + print_string(PRINT_FP, NULL, "TX: ", ""); + + if (stb[VNIFILTER_ENTRY_STATS_TX_BYTES]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_TX_BYTES]); + print_lluint(PRINT_ANY, "tx_bytes", "bytes %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_TX_PKTS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_TX_PKTS]); + print_lluint(PRINT_ANY, "tx_pkts", "pkts %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_TX_DROPS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_TX_DROPS]); + print_lluint(PRINT_ANY, "tx_drops", "drops %llu ", stat); + } + if (stb[VNIFILTER_ENTRY_STATS_TX_ERRORS]) { + stat = rta_getattr_u64(stb[VNIFILTER_ENTRY_STATS_TX_ERRORS]); + print_lluint(PRINT_ANY, "tx_errors", "errors %llu ", stat); + } + close_json_object(); +} + static void print_vni(struct rtattr *t, int ifindex) { struct rtattr *ttb[VXLAN_VNIFILTER_ENTRY_MAX+1]; @@ -242,6 +295,10 @@ static void print_vni(struct rtattr *t, int ifindex) &addr)); } } + + if (ttb[VXLAN_VNIFILTER_ENTRY_STATS]) + print_vnifilter_entry_stats(ttb[VXLAN_VNIFILTER_ENTRY_STATS]); + close_json_object(); print_string(PRINT_FP, NULL, "%s", _SL_); } @@ -310,6 +367,7 @@ static int print_vnifilter_rtm_filter(struct nlmsghdr *n, void *arg) static int vni_show(int argc, char **argv) { char *filter_dev = NULL; + __u8 flags = 0; int ret = 0; while (argc > 0) { @@ -330,25 +388,26 @@ static int vni_show(int argc, char **argv) new_json_obj(json); - if (!show_stats) { - if (rtnl_tunneldump_req(&rth, PF_BRIDGE, filter_index) < 0) { - perror("Cannot send dump request"); - exit(1); - } + if (show_stats) + flags = TUNNEL_MSG_FLAG_STATS; - if (!is_json_context()) { - printf("%-" __stringify(IFNAMSIZ) "s %-" - __stringify(VXLAN_ID_LEN) "s %-" - __stringify(15) "s", - "dev", "vni", "group/remote"); - printf("\n"); - } + if (rtnl_tunneldump_req(&rth, PF_BRIDGE, filter_index, flags) < 0) { + perror("Cannot send dump request"); + exit(1); + } - ret = rtnl_dump_filter(&rth, print_vnifilter_rtm_filter, NULL); - if (ret < 0) { - fprintf(stderr, "Dump ternminated\n"); - exit(1); - } + if (!is_json_context()) { + printf("%-" __stringify(IFNAMSIZ) "s %-" + __stringify(VXLAN_ID_LEN) "s %-" + __stringify(15) "s", + "dev", "vni", "group/remote"); + printf("\n"); + } + + ret = rtnl_dump_filter(&rth, print_vnifilter_rtm_filter, NULL); + if (ret < 0) { + fprintf(stderr, "Dump ternminated\n"); + exit(1); } delete_json_obj(); diff --git a/include/libnetlink.h b/include/libnetlink.h index a1ec91ec4..a7b0f3523 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -112,7 +112,8 @@ int rtnl_nexthop_bucket_dump_req(struct rtnl_handle *rth, int family, req_filter_fn_t filter_fn) __attribute__((warn_unused_result)); -int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex) +int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex, + __u8 flags) __attribute__((warn_unused_result)); struct rtnl_ctrl_data { diff --git a/lib/libnetlink.c b/lib/libnetlink.c index b3c3d0ba3..c27627fed 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -1610,7 +1610,8 @@ void nl_print_policy(const struct rtattr *attr, FILE *fp) } } -int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex) +int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex, + __u8 flags) { struct { struct nlmsghdr nlh; @@ -1622,6 +1623,7 @@ int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex) .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, .nlh.nlmsg_seq = rth->dump = ++rth->seq, .tmsg.family = family, + .tmsg.flags = flags, .tmsg.ifindex = ifindex, };