2017-10-04 20:10:04 -07:00
/*
* Copyright ( C ) 2017 Netronome Systems , Inc .
*
* This software is dual licensed under the GNU General License Version 2 ,
* June 1991 as shown in the file COPYING in the top - level directory of this
* source tree or the BSD 2 - Clause License provided below . You have the
* option to license this software under the complete terms of either license .
*
* The BSD 2 - Clause License :
*
* Redistribution and use in source and binary forms , with or
* without modification , are permitted provided that the following
* conditions are met :
*
* 1. Redistributions of source code must retain the above
* copyright notice , this list of conditions and the following
* disclaimer .
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the following
* disclaimer in the documentation and / or other materials
* provided with the distribution .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN
* ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
*/
/* Author: Jakub Kicinski <kubakici@wp.pl> */
# include <bfd.h>
# include <ctype.h>
# include <errno.h>
2017-10-23 09:24:06 -07:00
# include <getopt.h>
2017-10-04 20:10:04 -07:00
# include <linux/bpf.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <bpf.h>
# include "main.h"
2018-03-01 20:20:09 -08:00
# define BATCH_LINE_LEN_MAX 65536
# define BATCH_ARG_NB_MAX 4096
2017-10-04 20:10:04 -07:00
const char * bin_name ;
static int last_argc ;
static char * * last_argv ;
static int ( * last_do_help ) ( int argc , char * * argv ) ;
2017-10-23 09:24:07 -07:00
json_writer_t * json_wtr ;
bool pretty_output ;
bool json_output ;
2017-11-08 13:55:49 +09:00
bool show_pinned ;
tools: bpftool: show filenames of pinned objects
Added support to show filenames of pinned objects.
For example:
root@test# ./bpftool prog
3: tracepoint name tracepoint__irq tag f677a7dd722299a3
loaded_at Oct 26/11:39 uid 0
xlated 160B not jited memlock 4096B map_ids 4
pinned /sys/fs/bpf/softirq_prog
4: tracepoint name tracepoint__irq tag ea5dc530d00b92b6
loaded_at Oct 26/11:39 uid 0
xlated 392B not jited memlock 4096B map_ids 4,6
root@test# ./bpftool --json --pretty prog
[{
"id": 3,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "f677a7dd722299a3",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 160,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4
],
"pinned": ["/sys/fs/bpf/softirq_prog"
]
},{
"id": 4,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "ea5dc530d00b92b6",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 392,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4,6
],
"pinned": []
}
]
root@test# ./bpftool map
4: hash name start flags 0x0
key 4B value 16B max_entries 10240 memlock 1003520B
pinned /sys/fs/bpf/softirq_map1
5: hash name iptr flags 0x0
key 4B value 8B max_entries 10240 memlock 921600B
root@test# ./bpftool --json --pretty map
[{
"id": 4,
"type": "hash",
"name": "start",
"flags": 0,
"bytes_key": 4,
"bytes_value": 16,
"max_entries": 10240,
"bytes_memlock": 1003520,
"pinned": ["/sys/fs/bpf/softirq_map1"
]
},{
"id": 5,
"type": "hash",
"name": "iptr",
"flags": 0,
"bytes_key": 4,
"bytes_value": 8,
"max_entries": 10240,
"bytes_memlock": 921600,
"pinned": []
}
]
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-11-08 13:55:48 +09:00
struct pinned_obj_table prog_table ;
struct pinned_obj_table map_table ;
2017-10-04 20:10:04 -07:00
2017-11-28 17:44:29 -08:00
static void __noreturn clean_and_exit ( int i )
{
if ( json_output )
jsonw_destroy ( & json_wtr ) ;
exit ( i ) ;
}
2017-10-04 20:10:04 -07:00
void usage ( void )
{
last_do_help ( last_argc - 1 , last_argv + 1 ) ;
2017-11-28 17:44:29 -08:00
clean_and_exit ( - 1 ) ;
2017-10-04 20:10:04 -07:00
}
static int do_help ( int argc , char * * argv )
{
2017-10-23 09:24:14 -07:00
if ( json_output ) {
jsonw_null ( json_wtr ) ;
return 0 ;
}
2017-10-04 20:10:04 -07:00
fprintf ( stderr ,
2017-10-23 09:24:16 -07:00
" Usage: %s [OPTIONS] OBJECT { COMMAND | help } \n "
2017-10-04 20:10:04 -07:00
" %s batch file FILE \n "
2017-10-19 15:46:26 -07:00
" %s version \n "
2017-10-04 20:10:04 -07:00
" \n "
2017-12-13 15:18:54 +00:00
" OBJECT := { prog | map | cgroup } \n "
2017-10-23 09:24:16 -07:00
" " HELP_SPEC_OPTIONS " \n "
" " ,
2017-10-19 15:46:26 -07:00
bin_name , bin_name , bin_name ) ;
2017-10-04 20:10:04 -07:00
return 0 ;
}
2017-10-19 15:46:26 -07:00
static int do_version ( int argc , char * * argv )
{
2017-10-23 09:24:14 -07:00
if ( json_output ) {
jsonw_start_object ( json_wtr ) ;
jsonw_name ( json_wtr , " version " ) ;
2017-12-27 19:16:28 +00:00
jsonw_printf ( json_wtr , " \" %s \" " , BPFTOOL_VERSION ) ;
2017-10-23 09:24:14 -07:00
jsonw_end_object ( json_wtr ) ;
} else {
2017-12-27 19:16:28 +00:00
printf ( " %s v%s \n " , bin_name , BPFTOOL_VERSION ) ;
2017-10-23 09:24:14 -07:00
}
2017-10-19 15:46:26 -07:00
return 0 ;
}
2017-10-04 20:10:04 -07:00
int cmd_select ( const struct cmd * cmds , int argc , char * * argv ,
int ( * help ) ( int argc , char * * argv ) )
{
unsigned int i ;
last_argc = argc ;
last_argv = argv ;
last_do_help = help ;
if ( argc < 1 & & cmds [ 0 ] . func )
return cmds [ 0 ] . func ( argc , argv ) ;
for ( i = 0 ; cmds [ i ] . func ; i + + )
if ( is_prefix ( * argv , cmds [ i ] . cmd ) )
return cmds [ i ] . func ( argc - 1 , argv + 1 ) ;
help ( argc - 1 , argv + 1 ) ;
return - 1 ;
}
bool is_prefix ( const char * pfx , const char * str )
{
if ( ! pfx )
return false ;
if ( strlen ( str ) < strlen ( pfx ) )
return false ;
return ! memcmp ( str , pfx , strlen ( pfx ) ) ;
}
2017-10-19 15:46:19 -07:00
void fprint_hex ( FILE * f , void * arg , unsigned int n , const char * sep )
2017-10-04 20:10:04 -07:00
{
unsigned char * data = arg ;
unsigned int i ;
for ( i = 0 ; i < n ; i + + ) {
const char * pfx = " " ;
if ( ! i )
/* nothing */ ;
else if ( ! ( i % 16 ) )
2017-10-19 15:46:19 -07:00
fprintf ( f , " \n " ) ;
2017-10-04 20:10:04 -07:00
else if ( ! ( i % 8 ) )
2017-10-19 15:46:19 -07:00
fprintf ( f , " " ) ;
2017-10-04 20:10:04 -07:00
else
pfx = sep ;
2017-10-19 15:46:19 -07:00
fprintf ( f , " %s%02hhx " , i ? pfx : " " , data [ i ] ) ;
2017-10-04 20:10:04 -07:00
}
}
static int do_batch ( int argc , char * * argv ) ;
static const struct cmd cmds [ ] = {
{ " help " , do_help } ,
{ " batch " , do_batch } ,
{ " prog " , do_prog } ,
{ " map " , do_map } ,
2017-12-13 15:18:54 +00:00
{ " cgroup " , do_cgroup } ,
2017-10-19 15:46:26 -07:00
{ " version " , do_version } ,
2017-10-04 20:10:04 -07:00
{ 0 }
} ;
static int do_batch ( int argc , char * * argv )
{
2018-03-01 20:20:09 -08:00
char buf [ BATCH_LINE_LEN_MAX ] , contline [ BATCH_LINE_LEN_MAX ] ;
char * n_argv [ BATCH_ARG_NB_MAX ] ;
2017-10-04 20:10:04 -07:00
unsigned int lines = 0 ;
int n_argc ;
FILE * fp ;
2018-03-01 20:20:08 -08:00
char * cp ;
2017-10-04 20:10:04 -07:00
int err ;
2017-10-23 09:24:12 -07:00
int i ;
2017-10-04 20:10:04 -07:00
if ( argc < 2 ) {
2017-10-23 09:24:13 -07:00
p_err ( " too few parameters for batch " ) ;
2017-10-04 20:10:04 -07:00
return - 1 ;
} else if ( ! is_prefix ( * argv , " file " ) ) {
2017-10-23 09:24:13 -07:00
p_err ( " expected 'file', got: %s " , * argv ) ;
2017-10-04 20:10:04 -07:00
return - 1 ;
} else if ( argc > 2 ) {
2017-10-23 09:24:13 -07:00
p_err ( " too many parameters for batch " ) ;
2017-10-04 20:10:04 -07:00
return - 1 ;
}
NEXT_ARG ( ) ;
fp = fopen ( * argv , " r " ) ;
if ( ! fp ) {
2017-10-23 09:24:13 -07:00
p_err ( " Can't open file (%s): %s " , * argv , strerror ( errno ) ) ;
2017-10-04 20:10:04 -07:00
return - 1 ;
}
2017-10-23 09:24:12 -07:00
if ( json_output )
jsonw_start_array ( json_wtr ) ;
2017-10-04 20:10:04 -07:00
while ( fgets ( buf , sizeof ( buf ) , fp ) ) {
2018-03-01 20:20:08 -08:00
cp = strchr ( buf , ' # ' ) ;
if ( cp )
* cp = ' \0 ' ;
2017-10-04 20:10:04 -07:00
if ( strlen ( buf ) = = sizeof ( buf ) - 1 ) {
errno = E2BIG ;
break ;
}
2018-03-01 20:20:09 -08:00
/* Append continuation lines if any (coming after a line ending
* with ' \ ' in the batch file ) .
*/
while ( ( cp = strstr ( buf , " \\ \n " ) ) ! = NULL ) {
if ( ! fgets ( contline , sizeof ( contline ) , fp ) | |
strlen ( contline ) = = 0 ) {
p_err ( " missing continuation line on command %d " ,
lines ) ;
err = - 1 ;
goto err_close ;
}
cp = strchr ( contline , ' # ' ) ;
if ( cp )
* cp = ' \0 ' ;
if ( strlen ( buf ) + strlen ( contline ) + 1 > sizeof ( buf ) ) {
p_err ( " command %d is too long " , lines ) ;
err = - 1 ;
goto err_close ;
}
buf [ strlen ( buf ) - 2 ] = ' \0 ' ;
strcat ( buf , contline ) ;
}
2017-10-04 20:10:04 -07:00
n_argc = 0 ;
n_argv [ n_argc ] = strtok ( buf , " \t \n " ) ;
while ( n_argv [ n_argc ] ) {
n_argc + + ;
if ( n_argc = = ARRAY_SIZE ( n_argv ) ) {
2018-03-01 20:20:09 -08:00
p_err ( " command %d has too many arguments, skip " ,
2017-10-23 09:24:13 -07:00
lines ) ;
2017-10-04 20:10:04 -07:00
n_argc = 0 ;
break ;
}
n_argv [ n_argc ] = strtok ( NULL , " \t \n " ) ;
}
if ( ! n_argc )
continue ;
2017-10-23 09:24:12 -07:00
if ( json_output ) {
jsonw_start_object ( json_wtr ) ;
jsonw_name ( json_wtr , " command " ) ;
jsonw_start_array ( json_wtr ) ;
for ( i = 0 ; i < n_argc ; i + + )
jsonw_string ( json_wtr , n_argv [ i ] ) ;
jsonw_end_array ( json_wtr ) ;
jsonw_name ( json_wtr , " output " ) ;
}
2017-10-04 20:10:04 -07:00
err = cmd_select ( cmds , n_argc , n_argv , do_help ) ;
2017-10-23 09:24:12 -07:00
if ( json_output )
jsonw_end_object ( json_wtr ) ;
2017-10-04 20:10:04 -07:00
if ( err )
goto err_close ;
lines + + ;
}
if ( errno & & errno ! = ENOENT ) {
2018-02-14 22:42:55 -08:00
p_err ( " reading batch file failed: %s " , strerror ( errno ) ) ;
2017-10-04 20:10:04 -07:00
err = - 1 ;
} else {
2018-03-01 20:20:09 -08:00
p_info ( " processed %d commands " , lines ) ;
2017-10-04 20:10:04 -07:00
err = 0 ;
}
err_close :
fclose ( fp ) ;
2017-10-23 09:24:12 -07:00
if ( json_output )
jsonw_end_array ( json_wtr ) ;
2017-10-04 20:10:04 -07:00
return err ;
}
int main ( int argc , char * * argv )
{
2017-10-23 09:24:06 -07:00
static const struct option options [ ] = {
2017-10-23 09:24:07 -07:00
{ " json " , no_argument , NULL , ' j ' } ,
2017-10-23 09:24:06 -07:00
{ " help " , no_argument , NULL , ' h ' } ,
2017-10-23 09:24:07 -07:00
{ " pretty " , no_argument , NULL , ' p ' } ,
2017-10-23 09:24:06 -07:00
{ " version " , no_argument , NULL , ' V ' } ,
2017-11-08 13:55:49 +09:00
{ " bpffs " , no_argument , NULL , ' f ' } ,
2017-10-23 09:24:06 -07:00
{ 0 }
} ;
2017-10-23 09:24:07 -07:00
int opt , ret ;
2017-10-23 09:24:06 -07:00
last_do_help = do_help ;
2017-10-23 09:24:07 -07:00
pretty_output = false ;
json_output = false ;
2017-11-08 13:55:49 +09:00
show_pinned = false ;
2017-10-04 20:10:04 -07:00
bin_name = argv [ 0 ] ;
2017-10-23 09:24:06 -07:00
tools: bpftool: show filenames of pinned objects
Added support to show filenames of pinned objects.
For example:
root@test# ./bpftool prog
3: tracepoint name tracepoint__irq tag f677a7dd722299a3
loaded_at Oct 26/11:39 uid 0
xlated 160B not jited memlock 4096B map_ids 4
pinned /sys/fs/bpf/softirq_prog
4: tracepoint name tracepoint__irq tag ea5dc530d00b92b6
loaded_at Oct 26/11:39 uid 0
xlated 392B not jited memlock 4096B map_ids 4,6
root@test# ./bpftool --json --pretty prog
[{
"id": 3,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "f677a7dd722299a3",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 160,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4
],
"pinned": ["/sys/fs/bpf/softirq_prog"
]
},{
"id": 4,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "ea5dc530d00b92b6",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 392,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4,6
],
"pinned": []
}
]
root@test# ./bpftool map
4: hash name start flags 0x0
key 4B value 16B max_entries 10240 memlock 1003520B
pinned /sys/fs/bpf/softirq_map1
5: hash name iptr flags 0x0
key 4B value 8B max_entries 10240 memlock 921600B
root@test# ./bpftool --json --pretty map
[{
"id": 4,
"type": "hash",
"name": "start",
"flags": 0,
"bytes_key": 4,
"bytes_value": 16,
"max_entries": 10240,
"bytes_memlock": 1003520,
"pinned": ["/sys/fs/bpf/softirq_map1"
]
},{
"id": 5,
"type": "hash",
"name": "iptr",
"flags": 0,
"bytes_key": 4,
"bytes_value": 8,
"max_entries": 10240,
"bytes_memlock": 921600,
"pinned": []
}
]
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-11-08 13:55:48 +09:00
hash_init ( prog_table . table ) ;
hash_init ( map_table . table ) ;
2017-11-28 17:44:30 -08:00
opterr = 0 ;
2017-11-08 13:55:49 +09:00
while ( ( opt = getopt_long ( argc , argv , " Vhpjf " ,
2017-10-23 09:24:06 -07:00
options , NULL ) ) > = 0 ) {
switch ( opt ) {
case ' V ' :
return do_version ( argc , argv ) ;
case ' h ' :
return do_help ( argc , argv ) ;
2017-10-23 09:24:07 -07:00
case ' p ' :
pretty_output = true ;
/* fall through */
case ' j ' :
2017-11-28 17:44:28 -08:00
if ( ! json_output ) {
json_wtr = jsonw_new ( stdout ) ;
if ( ! json_wtr ) {
p_err ( " failed to create JSON writer " ) ;
return - 1 ;
}
json_output = true ;
}
jsonw_pretty ( json_wtr , pretty_output ) ;
2017-10-23 09:24:07 -07:00
break ;
2017-11-08 13:55:49 +09:00
case ' f ' :
show_pinned = true ;
break ;
2017-10-23 09:24:06 -07:00
default :
2017-11-28 17:44:30 -08:00
p_err ( " unrecognized option '%s' " , argv [ optind - 1 ] ) ;
if ( json_output )
clean_and_exit ( - 1 ) ;
else
usage ( ) ;
2017-10-23 09:24:06 -07:00
}
}
argc - = optind ;
argv + = optind ;
if ( argc < 0 )
usage ( ) ;
2017-10-04 20:10:04 -07:00
bfd_init ( ) ;
2017-10-23 09:24:07 -07:00
ret = cmd_select ( cmds , argc , argv , do_help ) ;
if ( json_output )
jsonw_destroy ( & json_wtr ) ;
2017-11-08 13:55:49 +09:00
if ( show_pinned ) {
delete_pinned_obj_table ( & prog_table ) ;
delete_pinned_obj_table ( & map_table ) ;
}
tools: bpftool: show filenames of pinned objects
Added support to show filenames of pinned objects.
For example:
root@test# ./bpftool prog
3: tracepoint name tracepoint__irq tag f677a7dd722299a3
loaded_at Oct 26/11:39 uid 0
xlated 160B not jited memlock 4096B map_ids 4
pinned /sys/fs/bpf/softirq_prog
4: tracepoint name tracepoint__irq tag ea5dc530d00b92b6
loaded_at Oct 26/11:39 uid 0
xlated 392B not jited memlock 4096B map_ids 4,6
root@test# ./bpftool --json --pretty prog
[{
"id": 3,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "f677a7dd722299a3",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 160,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4
],
"pinned": ["/sys/fs/bpf/softirq_prog"
]
},{
"id": 4,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "ea5dc530d00b92b6",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 392,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4,6
],
"pinned": []
}
]
root@test# ./bpftool map
4: hash name start flags 0x0
key 4B value 16B max_entries 10240 memlock 1003520B
pinned /sys/fs/bpf/softirq_map1
5: hash name iptr flags 0x0
key 4B value 8B max_entries 10240 memlock 921600B
root@test# ./bpftool --json --pretty map
[{
"id": 4,
"type": "hash",
"name": "start",
"flags": 0,
"bytes_key": 4,
"bytes_value": 16,
"max_entries": 10240,
"bytes_memlock": 1003520,
"pinned": ["/sys/fs/bpf/softirq_map1"
]
},{
"id": 5,
"type": "hash",
"name": "iptr",
"flags": 0,
"bytes_key": 4,
"bytes_value": 8,
"max_entries": 10240,
"bytes_memlock": 921600,
"pinned": []
}
]
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-11-08 13:55:48 +09:00
2017-10-23 09:24:07 -07:00
return ret ;
2017-10-04 20:10:04 -07:00
}