diff mbox series

[bpf-next] tools: bpftool: make it easier to feed hex bytes to bpftool

Message ID 20180418024634.8525-1-jakub.kicinski@netronome.com
State Accepted, archived
Delegated to: BPF Maintainers
Headers show
Series [bpf-next] tools: bpftool: make it easier to feed hex bytes to bpftool | expand

Commit Message

Jakub Kicinski April 18, 2018, 2:46 a.m. UTC
From: Quentin Monnet <quentin.monnet@netronome.com>

bpftool uses hexadecimal values when it dumps map contents:

    # bpftool map dump id 1337
    key: ff 13 37 ff  value: a1 b2 c3 d4 ff ff ff ff
    Found 1 element

In order to lookup or update values with bpftool, the natural reflex is
then to copy and paste the values to the command line, and to try to run
something like:

    # bpftool map update id 1337 key ff 13 37 ff \
            value 00 00 00 00 00 00 1a 2b
    Error: error parsing byte: ff

bpftool complains, because it uses strtoul() with a 0 base to parse the
bytes, and that without a "0x" prefix, the bytes are considered as
decimal values (or even octal if they start with "0").

To feed hexadecimal values instead, one needs to add "0x" prefixes
everywhere necessary:

    # bpftool map update id 1337 key 0xff 0x13 0x37 0xff \
            value 0 0 0 0 0 0 0x1a 0x2b

To make it easier to use hexadecimal values, add an optional "hex"
keyword to put after "key" or "value" to tell bpftool to consider the
digits as hexadecimal. We can now do:

    # bpftool map update id 1337 key hex ff 13 37 ff \
            value hex 0 0 0 0 0 0 1a 2b

Without the "hex" keyword, the bytes are still parsed according to
normal integer notation (decimal if no prefix, or hexadecimal or octal
if "0x" or "0" prefix is used, respectively).

The patch also add related documentation and bash completion for the
"hex" keyword.

Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Suggested-by: David Beckett <david.beckett@netronome.com>
Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 tools/bpf/bpftool/Documentation/bpftool-map.rst | 29 +++++++++++++++++--------
 tools/bpf/bpftool/bash-completion/bpftool       |  8 ++++---
 tools/bpf/bpftool/map.c                         | 17 ++++++++++-----
 3 files changed, 36 insertions(+), 18 deletions(-)

Comments

Daniel Borkmann April 18, 2018, 12:51 p.m. UTC | #1
On 04/18/2018 04:46 AM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
> 
> bpftool uses hexadecimal values when it dumps map contents:
> 
>     # bpftool map dump id 1337
>     key: ff 13 37 ff  value: a1 b2 c3 d4 ff ff ff ff
>     Found 1 element
> 
> In order to lookup or update values with bpftool, the natural reflex is
> then to copy and paste the values to the command line, and to try to run
> something like:
> 
>     # bpftool map update id 1337 key ff 13 37 ff \
>             value 00 00 00 00 00 00 1a 2b
>     Error: error parsing byte: ff
> 
> bpftool complains, because it uses strtoul() with a 0 base to parse the
> bytes, and that without a "0x" prefix, the bytes are considered as
> decimal values (or even octal if they start with "0").
> 
> To feed hexadecimal values instead, one needs to add "0x" prefixes
> everywhere necessary:
> 
>     # bpftool map update id 1337 key 0xff 0x13 0x37 0xff \
>             value 0 0 0 0 0 0 0x1a 0x2b
> 
> To make it easier to use hexadecimal values, add an optional "hex"
> keyword to put after "key" or "value" to tell bpftool to consider the
> digits as hexadecimal. We can now do:
> 
>     # bpftool map update id 1337 key hex ff 13 37 ff \
>             value hex 0 0 0 0 0 0 1a 2b
> 
> Without the "hex" keyword, the bytes are still parsed according to
> normal integer notation (decimal if no prefix, or hexadecimal or octal
> if "0x" or "0" prefix is used, respectively).
> 
> The patch also add related documentation and bash completion for the
> "hex" keyword.
> 
> Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
> Suggested-by: David Beckett <david.beckett@netronome.com>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>

Applied to bpf-next, thanks Quentin!
diff mbox series

Patch

diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
index 457e868bd32f..5f512b14bff9 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -23,10 +23,10 @@  MAP COMMANDS
 
 |	**bpftool** **map { show | list }**   [*MAP*]
 |	**bpftool** **map dump**    *MAP*
-|	**bpftool** **map update**  *MAP*  **key** *BYTES*   **value** *VALUE* [*UPDATE_FLAGS*]
-|	**bpftool** **map lookup**  *MAP*  **key** *BYTES*
-|	**bpftool** **map getnext** *MAP* [**key** *BYTES*]
-|	**bpftool** **map delete**  *MAP*  **key** *BYTES*
+|	**bpftool** **map update**  *MAP*  **key** [**hex**] *BYTES*   **value** [**hex**] *VALUE* [*UPDATE_FLAGS*]
+|	**bpftool** **map lookup**  *MAP*  **key** [**hex**] *BYTES*
+|	**bpftool** **map getnext** *MAP* [**key** [**hex**] *BYTES*]
+|	**bpftool** **map delete**  *MAP*  **key** [**hex**] *BYTES*
 |	**bpftool** **map pin**     *MAP*  *FILE*
 |	**bpftool** **map help**
 |
@@ -48,20 +48,26 @@  DESCRIPTION
 	**bpftool map dump**    *MAP*
 		  Dump all entries in a given *MAP*.
 
-	**bpftool map update**  *MAP*  **key** *BYTES*   **value** *VALUE* [*UPDATE_FLAGS*]
+	**bpftool map update**  *MAP*  **key** [**hex**] *BYTES*   **value** [**hex**] *VALUE* [*UPDATE_FLAGS*]
 		  Update map entry for a given *KEY*.
 
 		  *UPDATE_FLAGS* can be one of: **any** update existing entry
 		  or add if doesn't exit; **exist** update only if entry already
 		  exists; **noexist** update only if entry doesn't exist.
 
-	**bpftool map lookup**  *MAP*  **key** *BYTES*
+		  If the **hex** keyword is provided in front of the bytes
+		  sequence, the bytes are parsed as hexadeximal values, even if
+		  no "0x" prefix is added. If the keyword is not provided, then
+		  the bytes are parsed as decimal values, unless a "0x" prefix
+		  (for hexadecimal) or a "0" prefix (for octal) is provided.
+
+	**bpftool map lookup**  *MAP*  **key** [**hex**] *BYTES*
 		  Lookup **key** in the map.
 
-	**bpftool map getnext** *MAP* [**key** *BYTES*]
+	**bpftool map getnext** *MAP* [**key** [**hex**] *BYTES*]
 		  Get next key.  If *key* is not specified, get first key.
 
-	**bpftool map delete**  *MAP*  **key** *BYTES*
+	**bpftool map delete**  *MAP*  **key** [**hex**] *BYTES*
 		  Remove entry from the map.
 
 	**bpftool map pin**     *MAP*  *FILE*
@@ -98,7 +104,12 @@  EXAMPLES
   10: hash  name some_map  flags 0x0
 	key 4B  value 8B  max_entries 2048  memlock 167936B
 
-**# bpftool map update id 10 key 13 00 07 00 value 02 00 00 00 01 02 03 04**
+The following three commands are equivalent:
+
+|
+| **# bpftool map update id 10 key hex   20   c4   b7   00 value hex   0f   ff   ff   ab   01   02   03   4c**
+| **# bpftool map update id 10 key     0x20 0xc4 0xb7 0x00 value     0x0f 0xff 0xff 0xab 0x01 0x02 0x03 0x4c**
+| **# bpftool map update id 10 key       32  196  183    0 value       15  255  255  171    1    2    3   76**
 
 **# bpftool map lookup id 10 key 0 1 2 3**
 
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 490811b45fa7..71cc5dec3685 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -147,7 +147,7 @@  _bpftool()
 
     # Deal with simplest keywords
     case $prev in
-        help|key|opcodes|visual)
+        help|hex|opcodes|visual)
             return 0
             ;;
         tag)
@@ -283,7 +283,7 @@  _bpftool()
                             return 0
                             ;;
                         key)
-                            return 0
+                            COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
                             ;;
                         *)
                             _bpftool_once_attr 'key'
@@ -302,7 +302,7 @@  _bpftool()
                             return 0
                             ;;
                         key)
-                            return 0
+                            COMPREPLY+=( $( compgen -W 'hex' -- "$cur" ) )
                             ;;
                         value)
                             # We can have bytes, or references to a prog or a
@@ -321,6 +321,8 @@  _bpftool()
                                     return 0
                                     ;;
                                 *)
+                                    COMPREPLY+=( $( compgen -W 'hex' \
+                                        -- "$cur" ) )
                                     return 0
                                     ;;
                             esac
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index f509c86faede..a6cdb640a0d7 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -283,11 +283,16 @@  static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
 			  unsigned int n)
 {
-	unsigned int i = 0;
+	unsigned int i = 0, base = 0;
 	char *endptr;
 
+	if (is_prefix(*argv, "hex")) {
+		base = 16;
+		argv++;
+	}
+
 	while (i < n && argv[i]) {
-		val[i] = strtoul(argv[i], &endptr, 0);
+		val[i] = strtoul(argv[i], &endptr, base);
 		if (*endptr) {
 			p_err("error parsing byte: %s", argv[i]);
 			return NULL;
@@ -869,10 +874,10 @@  static int do_help(int argc, char **argv)
 	fprintf(stderr,
 		"Usage: %s %s { show | list }   [MAP]\n"
 		"       %s %s dump    MAP\n"
-		"       %s %s update  MAP  key BYTES value VALUE [UPDATE_FLAGS]\n"
-		"       %s %s lookup  MAP  key BYTES\n"
-		"       %s %s getnext MAP [key BYTES]\n"
-		"       %s %s delete  MAP  key BYTES\n"
+		"       %s %s update  MAP  key [hex] BYTES value [hex] VALUE [UPDATE_FLAGS]\n"
+		"       %s %s lookup  MAP  key [hex] BYTES\n"
+		"       %s %s getnext MAP [key [hex] BYTES]\n"
+		"       %s %s delete  MAP  key [hex] BYTES\n"
 		"       %s %s pin     MAP  FILE\n"
 		"       %s %s help\n"
 		"\n"