2018-11-07 16:12:02 -08:00
// SPDX-License-Identifier: GPL-2.0
# define _GNU_SOURCE
# include <pthread.h>
# include <inttypes.h>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <asm/types.h>
# include <sys/syscall.h>
# include <errno.h>
# include <string.h>
# include <linux/bpf.h>
# include <sys/socket.h>
# include <bpf/bpf.h>
# include <bpf/libbpf.h>
# include <sys/ioctl.h>
# include <linux/rtnetlink.h>
# include <signal.h>
# include <linux/perf_event.h>
2019-07-23 14:34:42 -07:00
# include <linux/err.h>
2018-11-07 16:12:02 -08:00
# include "bpf_rlimit.h"
# include "bpf_util.h"
# include "cgroup_helpers.h"
# include "test_tcpnotify.h"
# include "trace_helpers.h"
# define SOCKET_BUFFER_SIZE (getpagesize() < 8192L ? getpagesize() : 8192L)
pthread_t tid ;
int rx_callbacks ;
2019-07-23 14:34:42 -07:00
static void dummyfn ( void * ctx , int cpu , void * data , __u32 size )
2018-11-07 16:12:02 -08:00
{
struct tcp_notifier * t = data ;
if ( t - > type ! = 0xde | | t - > subtype ! = 0xad | |
t - > source ! = 0xbe | | t - > hash ! = 0xef )
2019-07-23 14:34:42 -07:00
return ;
2018-11-07 16:12:02 -08:00
rx_callbacks + + ;
}
2019-07-23 14:34:42 -07:00
void tcp_notifier_poller ( struct perf_buffer * pb )
2018-11-07 16:12:02 -08:00
{
2019-07-23 14:34:42 -07:00
int err ;
while ( 1 ) {
err = perf_buffer__poll ( pb , 100 ) ;
if ( err < 0 & & err ! = - EINTR ) {
printf ( " failed perf_buffer__poll: %d \n " , err ) ;
return ;
}
}
2018-11-07 16:12:02 -08:00
}
static void * poller_thread ( void * arg )
{
2019-07-23 14:34:42 -07:00
struct perf_buffer * pb = arg ;
2018-11-07 16:12:02 -08:00
2019-07-23 14:34:42 -07:00
tcp_notifier_poller ( pb ) ;
2018-11-07 16:12:02 -08:00
return arg ;
}
int verify_result ( const struct tcpnotify_globals * result )
{
return ( result - > ncalls > 0 & & result - > ncalls = = rx_callbacks ? 0 : 1 ) ;
}
int main ( int argc , char * * argv )
{
const char * file = " test_tcpnotify_kern.o " ;
2019-07-23 14:34:42 -07:00
struct bpf_map * perf_map , * global_map ;
struct perf_buffer_opts pb_opts = { } ;
2018-11-07 16:12:02 -08:00
struct tcpnotify_globals g = { 0 } ;
2019-07-23 14:34:42 -07:00
struct perf_buffer * pb = NULL ;
2018-11-07 16:12:02 -08:00
const char * cg_path = " /foo " ;
2019-07-23 14:34:42 -07:00
int prog_fd , rv , cg_fd = - 1 ;
2018-11-07 16:12:02 -08:00
int error = EXIT_FAILURE ;
struct bpf_object * obj ;
char test_script [ 80 ] ;
cpu_set_t cpuset ;
2019-07-23 14:34:42 -07:00
__u32 key = 0 ;
2018-11-07 16:12:02 -08:00
CPU_ZERO ( & cpuset ) ;
CPU_SET ( 0 , & cpuset ) ;
pthread_setaffinity_np ( pthread_self ( ) , sizeof ( cpu_set_t ) , & cpuset ) ;
if ( setup_cgroup_environment ( ) )
goto err ;
cg_fd = create_and_get_cgroup ( cg_path ) ;
2019-01-07 09:46:46 -08:00
if ( cg_fd < 0 )
2018-11-07 16:12:02 -08:00
goto err ;
if ( join_cgroup ( cg_path ) )
goto err ;
if ( bpf_prog_load ( file , BPF_PROG_TYPE_SOCK_OPS , & obj , & prog_fd ) ) {
printf ( " FAILED: load_bpf_file failed for: %s \n " , file ) ;
goto err ;
}
rv = bpf_prog_attach ( prog_fd , cg_fd , BPF_CGROUP_SOCK_OPS , 0 ) ;
if ( rv ) {
printf ( " FAILED: bpf_prog_attach: %d (%s) \n " ,
error , strerror ( errno ) ) ;
goto err ;
}
2019-07-23 14:34:42 -07:00
perf_map = bpf_object__find_map_by_name ( obj , " perf_event_map " ) ;
if ( ! perf_map ) {
printf ( " FAIL:map '%s' not found \n " , " perf_event_map " ) ;
2018-11-07 16:12:02 -08:00
goto err ;
2019-07-23 14:34:42 -07:00
}
2018-11-07 16:12:02 -08:00
2019-07-23 14:34:42 -07:00
global_map = bpf_object__find_map_by_name ( obj , " global_map " ) ;
if ( ! global_map ) {
printf ( " FAIL:map '%s' not found \n " , " global_map " ) ;
return - 1 ;
}
2018-11-07 16:12:02 -08:00
2019-07-23 14:34:42 -07:00
pb_opts . sample_cb = dummyfn ;
pb = perf_buffer__new ( bpf_map__fd ( perf_map ) , 8 , & pb_opts ) ;
if ( IS_ERR ( pb ) )
2018-11-07 16:12:02 -08:00
goto err ;
2019-07-23 14:34:42 -07:00
pthread_create ( & tid , NULL , poller_thread , pb ) ;
2018-11-07 16:12:02 -08:00
sprintf ( test_script ,
2019-01-17 11:56:12 -08:00
" iptables -A INPUT -p tcp --dport %d -j DROP " ,
2018-11-07 16:12:02 -08:00
TESTPORT ) ;
system ( test_script ) ;
sprintf ( test_script ,
2019-01-17 11:56:12 -08:00
" nc 127.0.0.1 %d < /etc/passwd > /dev/null 2>&1 " ,
2018-11-07 16:12:02 -08:00
TESTPORT ) ;
system ( test_script ) ;
sprintf ( test_script ,
2019-01-17 11:56:12 -08:00
" iptables -D INPUT -p tcp --dport %d -j DROP " ,
2018-11-07 16:12:02 -08:00
TESTPORT ) ;
system ( test_script ) ;
2019-07-23 14:34:42 -07:00
rv = bpf_map_lookup_elem ( bpf_map__fd ( global_map ) , & key , & g ) ;
2018-11-07 16:12:02 -08:00
if ( rv ! = 0 ) {
printf ( " FAILED: bpf_map_lookup_elem returns %d \n " , rv ) ;
goto err ;
}
sleep ( 10 ) ;
if ( verify_result ( & g ) ) {
printf ( " FAILED: Wrong stats Expected %d calls, got %d \n " ,
g . ncalls , rx_callbacks ) ;
goto err ;
}
printf ( " PASSED! \n " ) ;
error = 0 ;
err :
bpf_prog_detach ( cg_fd , BPF_CGROUP_SOCK_OPS ) ;
close ( cg_fd ) ;
cleanup_cgroup_environment ( ) ;
2019-07-23 14:34:42 -07:00
if ( ! IS_ERR_OR_NULL ( pb ) )
perf_buffer__free ( pb ) ;
2018-11-07 16:12:02 -08:00
return error ;
}