aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Aleksandrov <nikolay@nvidia.com>2022-05-08 04:53:40 +0000
committerDavid Ahern <dsahern@kernel.org>2022-05-08 09:50:34 -0600
commit40b50f153c52e14b1848c74fd09ffc9e51b75c8a (patch)
tree11c55a60e0e8b808465fdaecf474cee647430398
parentc7f12a156be0ff5593b280178ef61cb2e658f99e (diff)
downloadiproute2-40b50f153c52e14b1848c74fd09ffc9e51b75c8a.tar.gz
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 <nikolay@nvidia.com> Signed-off-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r--bridge/vni.c93
-rw-r--r--include/libnetlink.h3
-rw-r--r--lib/libnetlink.c4
3 files changed, 81 insertions, 19 deletions
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,
};