2015-07-01 02:14:03 +00:00
/*
* common eBPF ELF operations .
*
* Copyright ( C ) 2013 - 2015 Alexei Starovoitov < ast @ kernel . org >
* Copyright ( C ) 2015 Wang Nan < wangnan0 @ huawei . com >
* Copyright ( C ) 2015 Huawei Inc .
2016-07-04 11:02:42 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ;
* version 2.1 of the License ( not later ! )
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program ; if not , see < http : //www.gnu.org/licenses>
2015-07-01 02:14:03 +00:00
*/
# include <stdlib.h>
# include <memory.h>
# include <unistd.h>
# include <asm/unistd.h>
# include <linux/bpf.h>
# include "bpf.h"
/*
2017-02-27 14:29:28 -08:00
* When building perf , unistd . h is overridden . __NR_bpf is
2016-01-11 13:47:57 +00:00
* required to be defined explicitly .
2015-07-01 02:14:03 +00:00
*/
# ifndef __NR_bpf
# if defined(__i386__)
# define __NR_bpf 357
# elif defined(__x86_64__)
# define __NR_bpf 321
# elif defined(__aarch64__)
# define __NR_bpf 280
# else
# error __NR_bpf not defined. libbpf does not support your arch.
# endif
# endif
2017-02-11 20:37:08 +01:00
static inline __u64 ptr_to_u64 ( const void * ptr )
2015-07-01 02:14:06 +00:00
{
return ( __u64 ) ( unsigned long ) ptr ;
}
2017-02-11 20:37:08 +01:00
static inline int sys_bpf ( enum bpf_cmd cmd , union bpf_attr * attr ,
unsigned int size )
2015-07-01 02:14:03 +00:00
{
return syscall ( __NR_bpf , cmd , attr , size ) ;
}
int bpf_create_map ( enum bpf_map_type map_type , int key_size ,
2016-12-08 18:46:16 -08:00
int value_size , int max_entries , __u32 map_flags )
2015-07-01 02:14:03 +00:00
{
union bpf_attr attr ;
memset ( & attr , ' \0 ' , sizeof ( attr ) ) ;
attr . map_type = map_type ;
attr . key_size = key_size ;
attr . value_size = value_size ;
attr . max_entries = max_entries ;
2016-12-08 18:46:16 -08:00
attr . map_flags = map_flags ;
2015-07-01 02:14:03 +00:00
return sys_bpf ( BPF_MAP_CREATE , & attr , sizeof ( attr ) ) ;
}
2015-07-01 02:14:06 +00:00
2017-02-10 00:21:38 +01:00
int bpf_load_program ( enum bpf_prog_type type , const struct bpf_insn * insns ,
size_t insns_cnt , const char * license ,
2016-12-08 18:46:15 -08:00
__u32 kern_version , char * log_buf , size_t log_buf_sz )
2015-07-01 02:14:06 +00:00
{
int fd ;
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . prog_type = type ;
attr . insn_cnt = ( __u32 ) insns_cnt ;
attr . insns = ptr_to_u64 ( insns ) ;
attr . license = ptr_to_u64 ( license ) ;
attr . log_buf = ptr_to_u64 ( NULL ) ;
attr . log_size = 0 ;
attr . log_level = 0 ;
attr . kern_version = kern_version ;
fd = sys_bpf ( BPF_PROG_LOAD , & attr , sizeof ( attr ) ) ;
if ( fd > = 0 | | ! log_buf | | ! log_buf_sz )
return fd ;
/* Try again with log */
attr . log_buf = ptr_to_u64 ( log_buf ) ;
attr . log_size = log_buf_sz ;
attr . log_level = 1 ;
log_buf [ 0 ] = 0 ;
return sys_bpf ( BPF_PROG_LOAD , & attr , sizeof ( attr ) ) ;
}
2015-11-24 13:36:08 +00:00
2017-02-10 00:21:39 +01:00
int bpf_map_update_elem ( int fd , const void * key , const void * value ,
2016-12-08 18:46:15 -08:00
__u64 flags )
2015-11-24 13:36:08 +00:00
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . map_fd = fd ;
attr . key = ptr_to_u64 ( key ) ;
attr . value = ptr_to_u64 ( value ) ;
attr . flags = flags ;
return sys_bpf ( BPF_MAP_UPDATE_ELEM , & attr , sizeof ( attr ) ) ;
}
2016-11-26 07:03:25 +00:00
2017-02-10 00:21:40 +01:00
int bpf_map_lookup_elem ( int fd , const void * key , void * value )
2016-11-26 07:03:25 +00:00
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . map_fd = fd ;
attr . key = ptr_to_u64 ( key ) ;
attr . value = ptr_to_u64 ( value ) ;
return sys_bpf ( BPF_MAP_LOOKUP_ELEM , & attr , sizeof ( attr ) ) ;
}
2017-02-10 00:21:41 +01:00
int bpf_map_delete_elem ( int fd , const void * key )
2016-11-26 07:03:25 +00:00
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . map_fd = fd ;
attr . key = ptr_to_u64 ( key ) ;
return sys_bpf ( BPF_MAP_DELETE_ELEM , & attr , sizeof ( attr ) ) ;
}
2017-02-10 00:21:42 +01:00
int bpf_map_get_next_key ( int fd , const void * key , void * next_key )
2016-11-26 07:03:25 +00:00
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . map_fd = fd ;
attr . key = ptr_to_u64 ( key ) ;
attr . next_key = ptr_to_u64 ( next_key ) ;
return sys_bpf ( BPF_MAP_GET_NEXT_KEY , & attr , sizeof ( attr ) ) ;
}
int bpf_obj_pin ( int fd , const char * pathname )
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . pathname = ptr_to_u64 ( ( void * ) pathname ) ;
attr . bpf_fd = fd ;
return sys_bpf ( BPF_OBJ_PIN , & attr , sizeof ( attr ) ) ;
}
int bpf_obj_get ( const char * pathname )
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . pathname = ptr_to_u64 ( ( void * ) pathname ) ;
return sys_bpf ( BPF_OBJ_GET , & attr , sizeof ( attr ) ) ;
}
2016-12-14 14:05:26 -08:00
2017-02-10 20:28:24 -08:00
int bpf_prog_attach ( int prog_fd , int target_fd , enum bpf_attach_type type ,
unsigned int flags )
2016-12-14 14:05:26 -08:00
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . target_fd = target_fd ;
attr . attach_bpf_fd = prog_fd ;
attr . attach_type = type ;
2017-02-10 20:28:24 -08:00
attr . attach_flags = flags ;
2016-12-14 14:05:26 -08:00
return sys_bpf ( BPF_PROG_ATTACH , & attr , sizeof ( attr ) ) ;
}
int bpf_prog_detach ( int target_fd , enum bpf_attach_type type )
{
union bpf_attr attr ;
bzero ( & attr , sizeof ( attr ) ) ;
attr . target_fd = target_fd ;
attr . attach_type = type ;
return sys_bpf ( BPF_PROG_DETACH , & attr , sizeof ( attr ) ) ;
}