netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Quentin Monnet <quentin.monnet@netronome.com>
To: Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>
Cc: bpf@vger.kernel.org, netdev@vger.kernel.org,
	oss-drivers@netronome.com,
	Quentin Monnet <quentin.monnet@netronome.com>
Subject: [PATCH bpf-next 1/6] tools: bpftool: add --log-libbpf option to get debug info from libbpf
Date: Mon, 29 Apr 2019 10:52:22 +0100	[thread overview]
Message-ID: <20190429095227.9745-2-quentin.monnet@netronome.com> (raw)
In-Reply-To: <20190429095227.9745-1-quentin.monnet@netronome.com>

libbpf has three levels of priority for output: warn, info, debug. By
default, debug output is not printed to stderr.

Add a new "--log-libbpf LOG_LEVEL" option to bpftool to provide more
flexibility on the log level for libbpf. LOG_LEVEL is a comma-separated
list of levels of log to print ("warn", "info", "debug"). The value
corresponding to the default behaviour would be "warn,info".

Internally, we simply use the function provided by libbpf to replace the
default printing function by one that prints logs for all required
levels.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 .../bpftool/Documentation/bpftool-prog.rst    |  6 ++
 tools/bpf/bpftool/bash-completion/bpftool     | 41 ++++++++++++-
 tools/bpf/bpftool/main.c                      | 61 ++++++++++++++++---
 3 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index e8118544d118..77d9570488d1 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -174,6 +174,12 @@ OPTIONS
 		  Do not automatically attempt to mount any virtual file system
 		  (such as tracefs or BPF virtual file system) when necessary.
 
+	--log-libbpf *LOG_LEVEL*
+		  Set the log level for libbpf output when attempting to load
+		  programs. *LOG_LEVEL* must be a comma-separated list of the
+		  levels of information to print, which can be **warn**,
+		  **info** or **debug**. The default is **warn,info**.
+
 EXAMPLES
 ========
 **# bpftool prog show**
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 50e402a5a9c8..a232da1b158d 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -44,6 +44,34 @@ _bpftool_one_of_list()
     COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) )
 }
 
+# Complete a comma-separated list of items. For example:
+#     _bpftool_cslist "abc def ghi"
+# will suggest:
+#     - "abc" and "abc,"        to complete "a"
+#     - "abc,def" and "abc,ghi" to complete "abc,"
+#     - "abc,ghi,def"           to complete "abc,ghi,"
+_bpftool_cslist()
+{
+    local array_arg array_cur array_comp prevsubwords w ifs_back
+    read -r -a array_arg <<< "$*"
+    ifs_back=$IFS
+    IFS="," read -r -a array_cur <<< "$cur"
+    IFS=$ifs_back
+    prevsubwords=${cur%,*}
+    for w in "${array_arg[@]}"; do
+            if [[ ! "$cur" =~ "," ]]; then
+                array_comp+=( "$w" "$w," )
+            elif [[ ! "$cur" =~ "$w," ]]; then
+                if [[ "${#array_arg[@]}" > ${#array_cur[@]} ]]; then
+                    array_comp+=( "$prevsubwords,$w" "$prevsubwords,$w," )
+                else
+                    array_comp+=( "$prevsubwords,$w" )
+                fi
+            fi
+    done
+    COMPREPLY+=( $( compgen -W "${array_comp[*]}" -- "$cur" ) )
+}
+
 _bpftool_get_map_ids()
 {
     COMPREPLY+=( $( compgen -W "$( bpftool -jp map  2>&1 | \
@@ -181,7 +209,7 @@ _bpftool()
 
     # Deal with options
     if [[ ${words[cword]} == -* ]]; then
-        local c='--version --json --pretty --bpffs --mapcompat'
+        local c='--version --json --pretty --bpffs --mapcompat --log-libbpf'
         COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
         return 0
     fi
@@ -203,12 +231,23 @@ _bpftool()
             COMPREPLY=( $( compgen -W 'file' -- "$cur" ) )
             return 0
             ;;
+        --log-libbpf)
+            _bpftool_cslist 'warn info debug'
+            return 0
+            ;;
     esac
 
     # Remove all options so completions don't have to deal with them.
     local i
     for (( i=1; i < ${#words[@]}; )); do
         if [[ ${words[i]::1} == - ]]; then
+            # Remove arguments for options, if necessary
+            case ${words[i]} in
+                --log-libbpf)
+                    words=( "${words[@]:0:i+1}" "${words[@]:i+2}" )
+                    [[ $i -le $cword ]] && cword=$(( cword - 1 ))
+                    ;;
+            esac
             words=( "${words[@]:0:i}" "${words[@]:i+1}" )
             [[ $i -le $cword ]] && cword=$(( cword - 1 ))
         else
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 1ac1fc520e6a..6318be6feb5c 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -10,6 +10,7 @@
 #include <string.h>
 
 #include <bpf.h>
+#include <libbpf.h>
 
 #include "main.h"
 
@@ -26,6 +27,7 @@ bool json_output;
 bool show_pinned;
 bool block_mount;
 int bpf_flags;
+int log_level_libbpf;
 struct pinned_obj_table prog_table;
 struct pinned_obj_table map_table;
 
@@ -77,6 +79,46 @@ static int do_version(int argc, char **argv)
 	return 0;
 }
 
+static int __printf(2, 0)
+print_selected_levels(enum libbpf_print_level level, const char *format,
+		      va_list args)
+{
+	if (!(log_level_libbpf & (1 << level)))
+		return 0;
+
+	return vfprintf(stderr, format, args);
+}
+
+static int set_libbpf_loglevel(const char *log_str)
+{
+	char *log_str_cpy, *token;
+
+	log_str_cpy = strdup(log_str);
+	if (!log_str_cpy) {
+		p_err("mem alloc failed");
+		return -1;
+	}
+
+	token = strtok(log_str_cpy, ",");
+	while (token) {
+		if (is_prefix(token, "warn"))
+			log_level_libbpf |= (1 << LIBBPF_WARN);
+		else if (is_prefix(token, "info"))
+			log_level_libbpf |= (1 << LIBBPF_INFO);
+		else if (is_prefix(token, "debug"))
+			log_level_libbpf |= (1 << LIBBPF_DEBUG);
+		else
+			p_info("unrecognized log level for libbpf: %s", token);
+
+		token = strtok(NULL, ",");
+	}
+	free(log_str_cpy);
+
+	libbpf_set_print(print_selected_levels);
+
+	return 0;
+}
+
 int cmd_select(const struct cmd *cmds, int argc, char **argv,
 	       int (*help)(int argc, char **argv))
 {
@@ -310,13 +352,14 @@ static int do_batch(int argc, char **argv)
 int main(int argc, char **argv)
 {
 	static const struct option options[] = {
-		{ "json",	no_argument,	NULL,	'j' },
-		{ "help",	no_argument,	NULL,	'h' },
-		{ "pretty",	no_argument,	NULL,	'p' },
-		{ "version",	no_argument,	NULL,	'V' },
-		{ "bpffs",	no_argument,	NULL,	'f' },
-		{ "mapcompat",	no_argument,	NULL,	'm' },
-		{ "nomount",	no_argument,	NULL,	'n' },
+		{ "json",	no_argument,		NULL,	'j' },
+		{ "help",	no_argument,		NULL,	'h' },
+		{ "pretty",	no_argument,		NULL,	'p' },
+		{ "version",	no_argument,		NULL,	'V' },
+		{ "bpffs",	no_argument,		NULL,	'f' },
+		{ "mapcompat",	no_argument,		NULL,	'm' },
+		{ "nomount",	no_argument,		NULL,	'n' },
+		{ "log-libbpf",	required_argument,	NULL,	'd' },
 		{ 0 }
 	};
 	int opt, ret;
@@ -362,6 +405,10 @@ int main(int argc, char **argv)
 		case 'n':
 			block_mount = true;
 			break;
+		case 'd':
+			if (set_libbpf_loglevel(optarg))
+				return -1;
+			break;
 		default:
 			p_err("unrecognized option '%s'", argv[optind - 1]);
 			if (json_output)
-- 
2.17.1


  reply	other threads:[~2019-04-29  9:52 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-29  9:52 [PATCH bpf-next 0/6] tools: bpftool: add options for debug info from libbpf and verifier Quentin Monnet
2019-04-29  9:52 ` Quentin Monnet [this message]
2019-04-29 23:32   ` [PATCH bpf-next 1/6] tools: bpftool: add --log-libbpf option to get debug info from libbpf Y Song
2019-04-30  9:34     ` Quentin Monnet
2019-04-30 15:31       ` Y Song
2019-04-30 19:39         ` Jakub Kicinski
2019-04-29  9:52 ` [PATCH bpf-next 2/6] tools: bpftool: add --log-all option to print all possible log info Quentin Monnet
2019-04-29  9:52 ` [PATCH bpf-next 3/6] libbpf: add bpf_object__load_xattr() API function to pass log_level Quentin Monnet
2019-04-29  9:52 ` [PATCH bpf-next 4/6] bpf: make BPF_LOG_* flags available in UAPI header Quentin Monnet
2019-05-05  6:19   ` Alexei Starovoitov
2019-05-07 17:06     ` Quentin Monnet
2019-04-29  9:52 ` [PATCH bpf-next 5/6] tools: bpf: report latest changes from BPF UAPI header to tools Quentin Monnet
2019-04-29  9:52 ` [PATCH bpf-next 6/6] tools: bpftool: add --log-verifier option to print kernel debug logs Quentin Monnet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190429095227.9745-2-quentin.monnet@netronome.com \
    --to=quentin.monnet@netronome.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=netdev@vger.kernel.org \
    --cc=oss-drivers@netronome.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).