瀏覽代碼

Merge branch 'bpftool-add-a-version-command-and-fix-several-items'

Jakub Kicinski says:

====================
tools: bpftool: add a "version" command, and fix several items

Quentin says:

The first seven patches of this series bring several minor fixes to
bpftool. Please see individual commit logs for details.

Last patch adds a "version" commands to bpftool, which is in fact the
version of the kernel from which it was compiled.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 7 年之前
父節點
當前提交
a8e8c0ecb4

+ 4 - 4
tools/bpf/bpftool/Documentation/bpftool-prog.rst

@@ -11,8 +11,8 @@ SYNOPSIS
 ========
 
 |	**bpftool** prog show [*PROG*]
-|	**bpftool** prog dump xlated *PROG* [file *FILE*] [opcodes]
-|	**bpftool** prog dump jited  *PROG* [file *FILE*] [opcodes]
+|	**bpftool** prog dump xlated *PROG* [{file *FILE* | opcodes }]
+|	**bpftool** prog dump jited  *PROG* [{file *FILE* | opcodes }]
 |	**bpftool** prog pin *PROG* *FILE*
 |	**bpftool** prog help
 |
@@ -28,14 +28,14 @@ DESCRIPTION
 		  Output will start with program ID followed by program type and
 		  zero or more named attributes (depending on kernel version).
 
-	**bpftool prog dump xlated** *PROG* [**file** *FILE*] [**opcodes**]
+	**bpftool prog dump xlated** *PROG* [{ **file** *FILE* | **opcodes** }]
 		  Dump eBPF instructions of the program from the kernel.
 		  If *FILE* is specified image will be written to a file,
 		  otherwise it will be disassembled and printed to stdout.
 
 		  **opcodes** controls if raw opcodes will be printed.
 
-	**bpftool prog dump jited**  *PROG* [**file** *FILE*] [**opcodes**]
+	**bpftool prog dump jited**  *PROG* [{ **file** *FILE* | **opcodes** }]
 		  Dump jited image (host machine code) of the program.
 		  If *FILE* is specified image will be written to a file,
 		  otherwise it will be disassembled and printed to stdout.

+ 2 - 0
tools/bpf/bpftool/Documentation/bpftool.rst

@@ -14,6 +14,8 @@ SYNOPSIS
 
 	**bpftool** batch file *FILE*
 
+	**bpftool** version
+
 	*OBJECT* := { **map** | **program** }
 
 	*MAP-COMMANDS* :=

+ 17 - 5
tools/bpf/bpftool/main.c

@@ -37,6 +37,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <linux/bpf.h>
+#include <linux/version.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -62,13 +63,23 @@ static int do_help(int argc, char **argv)
 	fprintf(stderr,
 		"Usage: %s OBJECT { COMMAND | help }\n"
 		"       %s batch file FILE\n"
+		"       %s version\n"
 		"\n"
 		"       OBJECT := { prog | map }\n",
-		bin_name, bin_name);
+		bin_name, bin_name, bin_name);
 
 	return 0;
 }
 
+static int do_version(int argc, char **argv)
+{
+	printf("%s v%d.%d.%d\n", bin_name,
+	       LINUX_VERSION_CODE >> 16,
+	       LINUX_VERSION_CODE >> 8 & 0xf,
+	       LINUX_VERSION_CODE & 0xf);
+	return 0;
+}
+
 int cmd_select(const struct cmd *cmds, int argc, char **argv,
 	       int (*help)(int argc, char **argv))
 {
@@ -100,7 +111,7 @@ bool is_prefix(const char *pfx, const char *str)
 	return !memcmp(str, pfx, strlen(pfx));
 }
 
-void print_hex(void *arg, unsigned int n, const char *sep)
+void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep)
 {
 	unsigned char *data = arg;
 	unsigned int i;
@@ -111,13 +122,13 @@ void print_hex(void *arg, unsigned int n, const char *sep)
 		if (!i)
 			/* nothing */;
 		else if (!(i % 16))
-			printf("\n");
+			fprintf(f, "\n");
 		else if (!(i % 8))
-			printf("  ");
+			fprintf(f, "  ");
 		else
 			pfx = sep;
 
-		printf("%s%02hhx", i ? pfx : "", data[i]);
+		fprintf(f, "%s%02hhx", i ? pfx : "", data[i]);
 	}
 }
 
@@ -128,6 +139,7 @@ static const struct cmd cmds[] = {
 	{ "batch",	do_batch },
 	{ "prog",	do_prog },
 	{ "map",	do_map },
+	{ "version",	do_version },
 	{ 0 }
 };
 

+ 1 - 1
tools/bpf/bpftool/main.h

@@ -67,7 +67,7 @@ enum bpf_obj_type {
 extern const char *bin_name;
 
 bool is_prefix(const char *pfx, const char *str);
-void print_hex(void *arg, unsigned int n, const char *sep);
+void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
 void usage(void) __attribute__((noreturn));
 
 struct cmd {

+ 11 - 11
tools/bpf/bpftool/map.c

@@ -216,12 +216,12 @@ static void print_entry(struct bpf_map_info *info, unsigned char *key,
 			!break_names;
 
 		printf("key:%c", break_names ? '\n' : ' ');
-		print_hex(key, info->key_size, " ");
+		fprint_hex(stdout, key, info->key_size, " ");
 
 		printf(single_line ? "  " : "\n");
 
 		printf("value:%c", break_names ? '\n' : ' ');
-		print_hex(value, info->value_size, " ");
+		fprint_hex(stdout, value, info->value_size, " ");
 
 		printf("\n");
 	} else {
@@ -230,13 +230,13 @@ static void print_entry(struct bpf_map_info *info, unsigned char *key,
 		n = get_possible_cpus();
 
 		printf("key:\n");
-		print_hex(key, info->key_size, " ");
+		fprint_hex(stdout, key, info->key_size, " ");
 		printf("\n");
 		for (i = 0; i < n; i++) {
 			printf("value (CPU %02d):%c",
 			       i, info->value_size > 16 ? '\n' : ' ');
-			print_hex(value + i * info->value_size,
-				  info->value_size, " ");
+			fprint_hex(stdout, value + i * info->value_size,
+				   info->value_size, " ");
 			printf("\n");
 		}
 	}
@@ -252,7 +252,7 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
 		val[i] = strtoul(argv[i], &endptr, 0);
 		if (*endptr) {
 			err("error parsing byte: %s\n", argv[i]);
-			break;
+			return NULL;
 		}
 		i++;
 	}
@@ -492,8 +492,8 @@ static int do_dump(int argc, char **argv)
 			print_entry(&info, key, value);
 		} else {
 			info("can't lookup element with key: ");
-			print_hex(key, info.key_size, " ");
-			printf("\n");
+			fprint_hex(stderr, key, info.key_size, " ");
+			fprintf(stderr, "\n");
 		}
 
 		prev_key = key;
@@ -587,7 +587,7 @@ static int do_lookup(int argc, char **argv)
 		print_entry(&info, key, value);
 	} else if (errno == ENOENT) {
 		printf("key:\n");
-		print_hex(key, info.key_size, " ");
+		fprint_hex(stdout, key, info.key_size, " ");
 		printf("\n\nNot found\n");
 	} else {
 		err("lookup failed: %s\n", strerror(errno));
@@ -642,14 +642,14 @@ static int do_getnext(int argc, char **argv)
 
 	if (key) {
 		printf("key:\n");
-		print_hex(key, info.key_size, " ");
+		fprint_hex(stdout, key, info.key_size, " ");
 		printf("\n");
 	} else {
 		printf("key: None\n");
 	}
 
 	printf("next key:\n");
-	print_hex(nextkey, info.key_size, " ");
+	fprint_hex(stdout, nextkey, info.key_size, " ");
 	printf("\n");
 
 exit_free:

+ 21 - 9
tools/bpf/bpftool/prog.c

@@ -224,7 +224,7 @@ static int show_prog(int fd)
 		printf("name %s  ", info.name);
 
 	printf("tag ");
-	print_hex(info.tag, BPF_TAG_SIZE, "");
+	fprint_hex(stdout, info.tag, BPF_TAG_SIZE, "");
 	printf("\n");
 
 	if (info.load_time) {
@@ -275,8 +275,10 @@ static int do_show(int argc, char **argv)
 	while (true) {
 		err = bpf_prog_get_next_id(id, &id);
 		if (err) {
-			if (errno == ENOENT)
+			if (errno == ENOENT) {
+				err = 0;
 				break;
+			}
 			err("can't get next program: %s\n", strerror(errno));
 			if (errno == EINVAL)
 				err("kernel too old?\n");
@@ -311,20 +313,29 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
 static void dump_xlated(void *buf, unsigned int len, bool opcodes)
 {
 	struct bpf_insn *insn = buf;
+	bool double_insn = false;
 	unsigned int i;
 
 	for (i = 0; i < len / sizeof(*insn); i++) {
+		if (double_insn) {
+			double_insn = false;
+			continue;
+		}
+
+		double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
+
 		printf("% 4d: ", i);
 		print_bpf_insn(print_insn, NULL, insn + i, true);
 
 		if (opcodes) {
 			printf("       ");
-			print_hex(insn + i, 8, " ");
+			fprint_hex(stdout, insn + i, 8, " ");
+			if (double_insn && i < len - 1) {
+				printf(" ");
+				fprint_hex(stdout, insn + i + 1, 8, " ");
+			}
 			printf("\n");
 		}
-
-		if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW))
-			i++;
 	}
 }
 
@@ -414,7 +425,7 @@ static int do_dump(int argc, char **argv)
 	}
 
 	if (*member_len > buf_size) {
-		info("too many instructions returned\n");
+		err("too many instructions returned\n");
 		goto err_free;
 	}
 
@@ -458,8 +469,8 @@ static int do_help(int argc, char **argv)
 {
 	fprintf(stderr,
 		"Usage: %s %s show [PROG]\n"
-		"       %s %s dump xlated PROG [file FILE] [opcodes]\n"
-		"       %s %s dump jited  PROG [file FILE] [opcodes]\n"
+		"       %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
+		"       %s %s dump jited  PROG [{ file FILE | opcodes }]\n"
 		"       %s %s pin   PROG FILE\n"
 		"       %s %s help\n"
 		"\n"
@@ -473,6 +484,7 @@ static int do_help(int argc, char **argv)
 
 static const struct cmd cmds[] = {
 	{ "show",	do_show },
+	{ "help",	do_help },
 	{ "dump",	do_dump },
 	{ "pin",	do_pin },
 	{ 0 }