2018-05-14 10:00:18 -07:00
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
# include <stddef.h>
# include <string.h>
# include <linux/bpf.h>
# include <linux/if_ether.h>
# include <linux/if_packet.h>
# include <linux/ip.h>
# include <linux/ipv6.h>
# include <linux/in.h>
# include <linux/udp.h>
# include <linux/tcp.h>
# include <linux/pkt_cls.h>
# include <sys/socket.h>
2020-01-20 14:06:45 +01:00
# include <bpf/bpf_helpers.h>
# include <bpf/bpf_endian.h>
2018-05-14 10:00:18 -07:00
/* Sockmap sample program connects a client and a backend together
* using cgroups .
*
* client : X < - - - > frontend : 80 client : X < - - - > backend : 80
*
* For simplicity we hard code values here and bind 1 : 1. The hard
* coded values are part of the setup in sockmap . sh script that
* is associated with this BPF program .
*
* The bpf_printk is verbose and prints information as connections
* are established and verdicts are decided .
*/
2019-07-05 08:50:12 -07:00
struct {
__uint ( type , TEST_MAP_TYPE ) ;
__uint ( max_entries , 20 ) ;
__uint ( key_size , sizeof ( int ) ) ;
__uint ( value_size , sizeof ( int ) ) ;
} sock_map SEC ( " .maps " ) ;
struct {
__uint ( type , TEST_MAP_TYPE ) ;
__uint ( max_entries , 20 ) ;
__uint ( key_size , sizeof ( int ) ) ;
__uint ( value_size , sizeof ( int ) ) ;
} sock_map_txmsg SEC ( " .maps " ) ;
struct {
__uint ( type , TEST_MAP_TYPE ) ;
__uint ( max_entries , 20 ) ;
__uint ( key_size , sizeof ( int ) ) ;
__uint ( value_size , sizeof ( int ) ) ;
} sock_map_redir SEC ( " .maps " ) ;
struct {
__uint ( type , BPF_MAP_TYPE_ARRAY ) ;
__uint ( max_entries , 1 ) ;
__type ( key , int ) ;
__type ( value , int ) ;
} sock_apply_bytes SEC ( " .maps " ) ;
struct {
__uint ( type , BPF_MAP_TYPE_ARRAY ) ;
__uint ( max_entries , 1 ) ;
__type ( key , int ) ;
__type ( value , int ) ;
} sock_cork_bytes SEC ( " .maps " ) ;
struct {
__uint ( type , BPF_MAP_TYPE_ARRAY ) ;
__uint ( max_entries , 6 ) ;
__type ( key , int ) ;
__type ( value , int ) ;
} sock_bytes SEC ( " .maps " ) ;
struct {
__uint ( type , BPF_MAP_TYPE_ARRAY ) ;
__uint ( max_entries , 1 ) ;
__type ( key , int ) ;
__type ( value , int ) ;
} sock_redir_flags SEC ( " .maps " ) ;
struct {
__uint ( type , BPF_MAP_TYPE_ARRAY ) ;
__uint ( max_entries , 1 ) ;
__type ( key , int ) ;
__type ( value , int ) ;
} sock_skb_opts SEC ( " .maps " ) ;
2018-05-14 10:00:18 -07:00
SEC ( " sk_skb1 " )
int bpf_prog1 ( struct __sk_buff * skb )
{
return skb - > len ;
}
SEC ( " sk_skb2 " )
int bpf_prog2 ( struct __sk_buff * skb )
{
__u32 lport = skb - > local_port ;
__u32 rport = skb - > remote_port ;
int len , * f , ret , zero = 0 ;
__u64 flags = 0 ;
if ( lport = = 10000 )
ret = 10 ;
else
ret = 1 ;
len = ( __u32 ) skb - > data_end - ( __u32 ) skb - > data ;
f = bpf_map_lookup_elem ( & sock_skb_opts , & zero ) ;
if ( f & & * f ) {
ret = 3 ;
flags = * f ;
}
# ifdef SOCKMAP
return bpf_sk_redirect_map ( skb , & sock_map , ret , flags ) ;
# else
return bpf_sk_redirect_hash ( skb , & sock_map , & ret , flags ) ;
# endif
}
SEC ( " sockops " )
int bpf_sockmap ( struct bpf_sock_ops * skops )
{
__u32 lport , rport ;
int op , err = 0 , index , key , ret ;
op = ( int ) skops - > op ;
switch ( op ) {
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB :
lport = skops - > local_port ;
rport = skops - > remote_port ;
if ( lport = = 10000 ) {
ret = 1 ;
# ifdef SOCKMAP
err = bpf_sock_map_update ( skops , & sock_map , & ret ,
BPF_NOEXIST ) ;
# else
err = bpf_sock_hash_update ( skops , & sock_map , & ret ,
BPF_NOEXIST ) ;
# endif
}
break ;
case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB :
lport = skops - > local_port ;
rport = skops - > remote_port ;
if ( bpf_ntohl ( rport ) = = 10001 ) {
ret = 10 ;
# ifdef SOCKMAP
err = bpf_sock_map_update ( skops , & sock_map , & ret ,
BPF_NOEXIST ) ;
# else
err = bpf_sock_hash_update ( skops , & sock_map , & ret ,
BPF_NOEXIST ) ;
# endif
}
break ;
default :
break ;
}
return 0 ;
}
SEC ( " sk_msg1 " )
int bpf_prog4 ( struct sk_msg_md * msg )
{
2018-11-26 14:16:19 -08:00
int * bytes , zero = 0 , one = 1 , two = 2 , three = 3 , four = 4 , five = 5 ;
int * start , * end , * start_push , * end_push , * start_pop , * pop ;
2018-05-14 10:00:18 -07:00
bytes = bpf_map_lookup_elem ( & sock_apply_bytes , & zero ) ;
if ( bytes )
bpf_msg_apply_bytes ( msg , * bytes ) ;
bytes = bpf_map_lookup_elem ( & sock_cork_bytes , & zero ) ;
if ( bytes )
bpf_msg_cork_bytes ( msg , * bytes ) ;
2018-10-19 19:56:51 -07:00
start = bpf_map_lookup_elem ( & sock_bytes , & zero ) ;
end = bpf_map_lookup_elem ( & sock_bytes , & one ) ;
2018-05-14 10:00:18 -07:00
if ( start & & end )
bpf_msg_pull_data ( msg , * start , * end , 0 ) ;
2018-10-19 19:56:51 -07:00
start_push = bpf_map_lookup_elem ( & sock_bytes , & two ) ;
end_push = bpf_map_lookup_elem ( & sock_bytes , & three ) ;
if ( start_push & & end_push )
bpf_msg_push_data ( msg , * start_push , * end_push , 0 ) ;
2018-11-26 14:16:19 -08:00
start_pop = bpf_map_lookup_elem ( & sock_bytes , & four ) ;
pop = bpf_map_lookup_elem ( & sock_bytes , & five ) ;
if ( start_pop & & pop )
bpf_msg_pop_data ( msg , * start_pop , * pop , 0 ) ;
2018-05-14 10:00:18 -07:00
return SK_PASS ;
}
SEC ( " sk_msg2 " )
int bpf_prog6 ( struct sk_msg_md * msg )
{
2018-11-26 14:16:19 -08:00
int zero = 0 , one = 1 , two = 2 , three = 3 , four = 4 , five = 5 , key = 0 ;
int * bytes , * start , * end , * start_push , * end_push , * start_pop , * pop , * f ;
2018-05-14 10:00:18 -07:00
__u64 flags = 0 ;
bytes = bpf_map_lookup_elem ( & sock_apply_bytes , & zero ) ;
if ( bytes )
bpf_msg_apply_bytes ( msg , * bytes ) ;
bytes = bpf_map_lookup_elem ( & sock_cork_bytes , & zero ) ;
if ( bytes )
bpf_msg_cork_bytes ( msg , * bytes ) ;
2018-10-19 19:56:51 -07:00
start = bpf_map_lookup_elem ( & sock_bytes , & zero ) ;
end = bpf_map_lookup_elem ( & sock_bytes , & one ) ;
2018-05-14 10:00:18 -07:00
if ( start & & end )
bpf_msg_pull_data ( msg , * start , * end , 0 ) ;
2018-10-19 19:56:51 -07:00
start_push = bpf_map_lookup_elem ( & sock_bytes , & two ) ;
end_push = bpf_map_lookup_elem ( & sock_bytes , & three ) ;
if ( start_push & & end_push )
bpf_msg_push_data ( msg , * start_push , * end_push , 0 ) ;
2018-11-26 14:16:19 -08:00
start_pop = bpf_map_lookup_elem ( & sock_bytes , & four ) ;
pop = bpf_map_lookup_elem ( & sock_bytes , & five ) ;
if ( start_pop & & pop )
bpf_msg_pop_data ( msg , * start_pop , * pop , 0 ) ;
2018-05-14 10:00:18 -07:00
f = bpf_map_lookup_elem ( & sock_redir_flags , & zero ) ;
if ( f & & * f ) {
key = 2 ;
flags = * f ;
}
# ifdef SOCKMAP
return bpf_msg_redirect_map ( msg , & sock_map_redir , key , flags ) ;
# else
return bpf_msg_redirect_hash ( msg , & sock_map_redir , & key , flags ) ;
# endif
}
2020-05-13 12:13:27 -07:00
SEC ( " sk_msg3 " )
2018-05-14 10:00:18 -07:00
int bpf_prog8 ( struct sk_msg_md * msg )
{
void * data_end = ( void * ) ( long ) msg - > data_end ;
void * data = ( void * ) ( long ) msg - > data ;
int ret = 0 , * bytes , zero = 0 ;
bytes = bpf_map_lookup_elem ( & sock_apply_bytes , & zero ) ;
if ( bytes ) {
ret = bpf_msg_apply_bytes ( msg , * bytes ) ;
if ( ret )
return SK_DROP ;
} else {
return SK_DROP ;
}
return SK_PASS ;
}
2020-05-13 12:13:27 -07:00
SEC ( " sk_msg4 " )
2018-05-14 10:00:18 -07:00
int bpf_prog9 ( struct sk_msg_md * msg )
{
void * data_end = ( void * ) ( long ) msg - > data_end ;
void * data = ( void * ) ( long ) msg - > data ;
int ret = 0 , * bytes , zero = 0 ;
bytes = bpf_map_lookup_elem ( & sock_cork_bytes , & zero ) ;
if ( bytes ) {
if ( ( ( __u64 ) data_end - ( __u64 ) data ) > = * bytes )
return SK_PASS ;
ret = bpf_msg_cork_bytes ( msg , * bytes ) ;
if ( ret )
return SK_DROP ;
}
return SK_PASS ;
}
2020-05-13 12:13:27 -07:00
SEC ( " sk_msg5 " )
2018-05-14 10:00:18 -07:00
int bpf_prog10 ( struct sk_msg_md * msg )
{
2018-11-26 14:16:19 -08:00
int * bytes , * start , * end , * start_push , * end_push , * start_pop , * pop ;
int zero = 0 , one = 1 , two = 2 , three = 3 , four = 4 , five = 5 ;
2018-05-14 10:00:18 -07:00
bytes = bpf_map_lookup_elem ( & sock_apply_bytes , & zero ) ;
if ( bytes )
bpf_msg_apply_bytes ( msg , * bytes ) ;
bytes = bpf_map_lookup_elem ( & sock_cork_bytes , & zero ) ;
if ( bytes )
bpf_msg_cork_bytes ( msg , * bytes ) ;
2018-10-19 19:56:51 -07:00
start = bpf_map_lookup_elem ( & sock_bytes , & zero ) ;
end = bpf_map_lookup_elem ( & sock_bytes , & one ) ;
2018-05-14 10:00:18 -07:00
if ( start & & end )
bpf_msg_pull_data ( msg , * start , * end , 0 ) ;
2018-10-19 19:56:51 -07:00
start_push = bpf_map_lookup_elem ( & sock_bytes , & two ) ;
end_push = bpf_map_lookup_elem ( & sock_bytes , & three ) ;
if ( start_push & & end_push )
bpf_msg_push_data ( msg , * start_push , * end_push , 0 ) ;
2018-11-26 14:16:19 -08:00
start_pop = bpf_map_lookup_elem ( & sock_bytes , & four ) ;
pop = bpf_map_lookup_elem ( & sock_bytes , & five ) ;
if ( start_pop & & pop )
bpf_msg_pop_data ( msg , * start_pop , * pop , 0 ) ;
2018-05-14 10:00:18 -07:00
return SK_DROP ;
}
int _version SEC ( " version " ) = 1 ;
char _license [ ] SEC ( " license " ) = " GPL " ;