bpf: add sample usages for persistent maps/progs
This patch adds a couple of stand-alone examples on how BPF_OBJ_PIN
and BPF_OBJ_GET commands can be used.
Example with maps:
# ./fds_example -F /sys/fs/bpf/m -P -m -k 1 -v 42
bpf: map fd:3 (Success)
bpf: pin ret:(0,Success)
bpf: fd:3 u->(1:42) ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):42 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1 -v 24
bpf: get fd:3 (Success)
bpf: fd:3 u->(1:24) ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):24 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -P -m
bpf: map fd:3 (Success)
bpf: pin ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):0 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -G -m
bpf: get fd:3 (Success)
Example with progs:
# ./fds_example -F /sys/fs/bpf/p -P -p
bpf: prog fd:3 (Success)
bpf: pin ret:(0,Success)
bpf sock:4 <- fd:3 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p -G -p
bpf: get fd:3 (Success)
bpf: sock:4 <- fd:3 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p2 -P -p -o ./sockex1_kern.o
bpf: prog fd:5 (Success)
bpf: pin ret:(0,Success)
bpf: sock:3 <- fd:5 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p2 -G -p
bpf: get fd:3 (Success)
bpf: sock:4 <- fd:3 attached ret:(0,Success)
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-10-29 14:58:10 +01:00
# include <linux/unistd.h>
# include <linux/bpf.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdint.h>
# include <unistd.h>
# include <string.h>
# include <assert.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/socket.h>
# include "bpf_load.h"
# include "libbpf.h"
# define BPF_F_PIN (1 << 0)
# define BPF_F_GET (1 << 1)
# define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET)
# define BPF_F_KEY (1 << 2)
# define BPF_F_VAL (1 << 3)
# define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL)
# define BPF_M_UNSPEC 0
# define BPF_M_MAP 1
# define BPF_M_PROG 2
static void usage ( void )
{
printf ( " Usage: fds_example [...] \n " ) ;
printf ( " -F <file> File to pin/get object \n " ) ;
printf ( " -P |- pin object \n " ) ;
printf ( " -G `- get object \n " ) ;
printf ( " -m eBPF map mode \n " ) ;
printf ( " -k <key> |- map key \n " ) ;
printf ( " -v <value> `- map value \n " ) ;
printf ( " -p eBPF prog mode \n " ) ;
printf ( " -o <object> `- object file \n " ) ;
printf ( " -h Display this help. \n " ) ;
}
static int bpf_map_create ( void )
{
return bpf_create_map ( BPF_MAP_TYPE_ARRAY , sizeof ( uint32_t ) ,
2016-03-07 21:57:20 -08:00
sizeof ( uint32_t ) , 1024 , 0 ) ;
bpf: add sample usages for persistent maps/progs
This patch adds a couple of stand-alone examples on how BPF_OBJ_PIN
and BPF_OBJ_GET commands can be used.
Example with maps:
# ./fds_example -F /sys/fs/bpf/m -P -m -k 1 -v 42
bpf: map fd:3 (Success)
bpf: pin ret:(0,Success)
bpf: fd:3 u->(1:42) ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):42 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1 -v 24
bpf: get fd:3 (Success)
bpf: fd:3 u->(1:24) ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):24 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -P -m
bpf: map fd:3 (Success)
bpf: pin ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -G -m -k 1
bpf: get fd:3 (Success)
bpf: fd:3 l->(1):0 ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/m2 -G -m
bpf: get fd:3 (Success)
Example with progs:
# ./fds_example -F /sys/fs/bpf/p -P -p
bpf: prog fd:3 (Success)
bpf: pin ret:(0,Success)
bpf sock:4 <- fd:3 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p -G -p
bpf: get fd:3 (Success)
bpf: sock:4 <- fd:3 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p2 -P -p -o ./sockex1_kern.o
bpf: prog fd:5 (Success)
bpf: pin ret:(0,Success)
bpf: sock:3 <- fd:5 attached ret:(0,Success)
# ./fds_example -F /sys/fs/bpf/p2 -G -p
bpf: get fd:3 (Success)
bpf: sock:4 <- fd:3 attached ret:(0,Success)
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-10-29 14:58:10 +01:00
}
static int bpf_prog_create ( const char * object )
{
static const struct bpf_insn insns [ ] = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ;
if ( object ) {
assert ( ! load_bpf_file ( ( char * ) object ) ) ;
return prog_fd [ 0 ] ;
} else {
return bpf_prog_load ( BPF_PROG_TYPE_SOCKET_FILTER ,
insns , sizeof ( insns ) , " GPL " , 0 ) ;
}
}
static int bpf_do_map ( const char * file , uint32_t flags , uint32_t key ,
uint32_t value )
{
int fd , ret ;
if ( flags & BPF_F_PIN ) {
fd = bpf_map_create ( ) ;
printf ( " bpf: map fd:%d (%s) \n " , fd , strerror ( errno ) ) ;
assert ( fd > 0 ) ;
ret = bpf_obj_pin ( fd , file ) ;
printf ( " bpf: pin ret:(%d,%s) \n " , ret , strerror ( errno ) ) ;
assert ( ret = = 0 ) ;
} else {
fd = bpf_obj_get ( file ) ;
printf ( " bpf: get fd:%d (%s) \n " , fd , strerror ( errno ) ) ;
assert ( fd > 0 ) ;
}
if ( ( flags & BPF_F_KEY_VAL ) = = BPF_F_KEY_VAL ) {
ret = bpf_update_elem ( fd , & key , & value , 0 ) ;
printf ( " bpf: fd:%d u->(%u:%u) ret:(%d,%s) \n " , fd , key , value ,
ret , strerror ( errno ) ) ;
assert ( ret = = 0 ) ;
} else if ( flags & BPF_F_KEY ) {
ret = bpf_lookup_elem ( fd , & key , & value ) ;
printf ( " bpf: fd:%d l->(%u):%u ret:(%d,%s) \n " , fd , key , value ,
ret , strerror ( errno ) ) ;
assert ( ret = = 0 ) ;
}
return 0 ;
}
static int bpf_do_prog ( const char * file , uint32_t flags , const char * object )
{
int fd , sock , ret ;
if ( flags & BPF_F_PIN ) {
fd = bpf_prog_create ( object ) ;
printf ( " bpf: prog fd:%d (%s) \n " , fd , strerror ( errno ) ) ;
assert ( fd > 0 ) ;
ret = bpf_obj_pin ( fd , file ) ;
printf ( " bpf: pin ret:(%d,%s) \n " , ret , strerror ( errno ) ) ;
assert ( ret = = 0 ) ;
} else {
fd = bpf_obj_get ( file ) ;
printf ( " bpf: get fd:%d (%s) \n " , fd , strerror ( errno ) ) ;
assert ( fd > 0 ) ;
}
sock = open_raw_sock ( " lo " ) ;
assert ( sock > 0 ) ;
ret = setsockopt ( sock , SOL_SOCKET , SO_ATTACH_BPF , & fd , sizeof ( fd ) ) ;
printf ( " bpf: sock:%d <- fd:%d attached ret:(%d,%s) \n " , sock , fd ,
ret , strerror ( errno ) ) ;
assert ( ret = = 0 ) ;
return 0 ;
}
int main ( int argc , char * * argv )
{
const char * file = NULL , * object = NULL ;
uint32_t key = 0 , value = 0 , flags = 0 ;
int opt , mode = BPF_M_UNSPEC ;
while ( ( opt = getopt ( argc , argv , " F:PGmk:v:po: " ) ) ! = - 1 ) {
switch ( opt ) {
/* General args */
case ' F ' :
file = optarg ;
break ;
case ' P ' :
flags | = BPF_F_PIN ;
break ;
case ' G ' :
flags | = BPF_F_GET ;
break ;
/* Map-related args */
case ' m ' :
mode = BPF_M_MAP ;
break ;
case ' k ' :
key = strtoul ( optarg , NULL , 0 ) ;
flags | = BPF_F_KEY ;
break ;
case ' v ' :
value = strtoul ( optarg , NULL , 0 ) ;
flags | = BPF_F_VAL ;
break ;
/* Prog-related args */
case ' p ' :
mode = BPF_M_PROG ;
break ;
case ' o ' :
object = optarg ;
break ;
default :
goto out ;
}
}
if ( ! ( flags & BPF_F_PIN_GET ) | | ! file )
goto out ;
switch ( mode ) {
case BPF_M_MAP :
return bpf_do_map ( file , flags , key , value ) ;
case BPF_M_PROG :
return bpf_do_prog ( file , flags , object ) ;
}
out :
usage ( ) ;
return - 1 ;
}