From c69190bb2b9a3c0f105ea630d328b294aa7810d7 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Wed, 23 Dec 2020 15:22:32 +0100
Subject: xdp: op-mode: T2666: support per interface statistics

---
 op-mode-definitions/show-interfaces-bonding.xml  |  6 +++
 op-mode-definitions/show-interfaces-ethernet.xml |  6 +++
 src/op_mode/show_xdp_stats.sh                    |  7 ++++
 src/xdp/common/common.mk                         |  2 +-
 src/xdp/utils/xdp_stats.c                        | 49 +++++++++++++-----------
 5 files changed, 46 insertions(+), 24 deletions(-)
 create mode 100755 src/op_mode/show_xdp_stats.sh

diff --git a/op-mode-definitions/show-interfaces-bonding.xml b/op-mode-definitions/show-interfaces-bonding.xml
index c1c76b059..f6d9b3508 100644
--- a/op-mode-definitions/show-interfaces-bonding.xml
+++ b/op-mode-definitions/show-interfaces-bonding.xml
@@ -42,6 +42,12 @@
                   </leafNode>
                 </children>
               </tagNode>
+              <leafNode name="xdp">
+                <properties>
+                  <help>Show eXpress Data Path statistics</help>
+                </properties>
+                <command>sudo ${vyos_op_scripts_dir}/show_xdp_stats.sh bonding "$4"</command>
+              </leafNode>
             </children>
           </tagNode>
           <node name="bonding">
diff --git a/op-mode-definitions/show-interfaces-ethernet.xml b/op-mode-definitions/show-interfaces-ethernet.xml
index bdcfa55f1..fc79f44bf 100644
--- a/op-mode-definitions/show-interfaces-ethernet.xml
+++ b/op-mode-definitions/show-interfaces-ethernet.xml
@@ -68,6 +68,12 @@
                   </leafNode>
                 </children>
               </tagNode>
+              <leafNode name="xdp">
+                <properties>
+                  <help>Show eXpress Data Path statistics</help>
+                </properties>
+                <command>sudo ${vyos_op_scripts_dir}/show_xdp_stats.sh ethernet "$4"</command>
+              </leafNode>
             </children>
           </tagNode>
           <node name="ethernet">
diff --git a/src/op_mode/show_xdp_stats.sh b/src/op_mode/show_xdp_stats.sh
new file mode 100755
index 000000000..a4ef33107
--- /dev/null
+++ b/src/op_mode/show_xdp_stats.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if cli-shell-api existsEffective interfaces $1 $2 xdp; then
+    /usr/sbin/xdp_stats --dev "$2"
+else
+    echo "XDP not enabled on $2"
+fi
diff --git a/src/xdp/common/common.mk b/src/xdp/common/common.mk
index 89aac68ef..ebe23a9ed 100644
--- a/src/xdp/common/common.mk
+++ b/src/xdp/common/common.mk
@@ -39,7 +39,7 @@ KERN_USER_H ?= $(wildcard common_kern_user.h)
 CFLAGS ?= -g -I../include/
 BPF_CFLAGS ?= -I../include/
 
-LIBS = -l:libbpf.a -lelf -lz $(USER_LIBS)
+LIBS = -l:libbpf.a -lelf $(USER_LIBS)
 
 all: llvm-check $(USER_TARGETS) $(XDP_OBJ) $(COPY_LOADER) $(COPY_STATS)
 
diff --git a/src/xdp/utils/xdp_stats.c b/src/xdp/utils/xdp_stats.c
index 5dbec8351..f9fa7438f 100644
--- a/src/xdp/utils/xdp_stats.c
+++ b/src/xdp/utils/xdp_stats.c
@@ -197,6 +197,7 @@ static int stats_poll(const char *pin_dir, int map_fd, __u32 id,
 {
 	struct bpf_map_info info = {};
 	struct stats_record prev, record = { 0 };
+	int counter = 0;
 
 	/* Trick to pretty printf with thousands separators use %' */
 	setlocale(LC_NUMERIC, "en_US");
@@ -219,6 +220,10 @@ static int stats_poll(const char *pin_dir, int map_fd, __u32 id,
 		stats_collect(map_fd, map_type, &record);
 		stats_print(&record, &prev);
 		sleep(interval);
+		counter++;
+		if (counter > 1) {
+			return 0;
+		}
 	}
 
 	return 0;
@@ -265,31 +270,29 @@ int main(int argc, char **argv)
 		return EXIT_FAIL_OPTION;
 	}
 
-	for ( ;; ) {
-		stats_map_fd = open_bpf_map_file(pin_dir, "xdp_stats_map", &info);
-		if (stats_map_fd < 0) {
-			return EXIT_FAIL_BPF;
-		}
-
-		/* check map info, e.g. datarec is expected size */
-		err = check_map_fd_info(&info, &map_expect);
-		if (err) {
-			fprintf(stderr, "ERR: map via FD not compatible\n");
-			return err;
-		}
-		if (verbose) {
-			printf("\nCollecting stats from BPF map\n");
-			printf(" - BPF map (bpf_map_type:%d) id:%d name:%s"
-			       " key_size:%d value_size:%d max_entries:%d\n",
-			       info.type, info.id, info.name,
-			       info.key_size, info.value_size, info.max_entries
-			       );
-		}
+	stats_map_fd = open_bpf_map_file(pin_dir, "xdp_stats_map", &info);
+	if (stats_map_fd < 0) {
+		return EXIT_FAIL_BPF;
+	}
 
-		err = stats_poll(pin_dir, stats_map_fd, info.id, info.type, interval);
-		if (err < 0)
-			return err;
+	/* check map info, e.g. datarec is expected size */
+	err = check_map_fd_info(&info, &map_expect);
+	if (err) {
+		fprintf(stderr, "ERR: map via FD not compatible\n");
+		return err;
 	}
+	if (verbose) {
+	printf("\nCollecting stats from BPF map\n");
+	printf(" - BPF map (bpf_map_type:%d) id:%d name:%s"
+	       " key_size:%d value_size:%d max_entries:%d\n",
+	       info.type, info.id, info.name,
+	       info.key_size, info.value_size, info.max_entries
+	       );
+	}
+
+	err = stats_poll(pin_dir, stats_map_fd, info.id, info.type, interval);
+	if (err < 0)
+		return err;
 
 	return EXIT_OK;
 }
-- 
cgit v1.2.3