2023-02-10 14:22:40 +08:00
# include <assert.h>
# include <netinet/ip.h>
# include <netinet/udp.h>
# include <netinet/ether.h>
# include <marsio.h>
# include <MESA/MESA_prof_load.h>
# include "log.h"
# include "sce.h"
# include "g_vxlan.h"
# include "ctrl_packet.h"
/*
* add : vxlan_hdr
* del : marsio_buff_reset ( )
* + - - - - + NF2SF + - - - - +
* | | - - - - - - - - - - - - - - - - - - - - - - - - - - - > | |
* | | | |
* | | - - - - - - - + | | - - - - - - - +
* | NF | | NF2NF ( undo ) | SF | | SF2SF ( del old vxlan_hdr ; add new vxlan_hdr )
* | | < - - - - - - + | | < - - - - - - +
* | | | |
* | | < - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
* | | SF2NF | |
* + - - - + del : vxlan_hdr + - - - - +
* add : session_id + route_ctx + sid
*/
/******************************************************************************
* Struct
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define RX_BURST_MAX 128
struct config
{
int bypass_all_traffic ;
int rx_burst_max ;
char app_symbol [ 256 ] ;
char dev_endpoint [ 256 ] ;
char dev_nf_interface [ 256 ] ;
char default_src_ip [ 16 ] ;
char default_dst_ip [ 16 ] ;
char default_src_mac [ 32 ] ;
char default_dst_mac [ 32 ] ;
} ;
struct device
{
struct mr_vdev * mr_dev ;
struct mr_sendpath * mr_path ;
} ;
struct packet_io
{
int thread_num ;
struct mr_instance * instance ;
struct device dev_nf_interface ;
struct device dev_endpoint ;
struct config config ;
} ;
enum raw_pkt_action
{
RAW_PKT_ERR_BYPASS ,
RAW_PKT_HIT_BYPASS ,
RAW_PKT_HIT_BLOCK ,
RAW_PKT_HIT_FORWARD ,
} ;
enum inject_pkt_action
{
INJT_PKT_ERR_DROP ,
INJT_PKT_HIT_BLOCK ,
INJT_PKT_HIT_FWD2SF , // forward to service function
INJT_PKT_HIT_FWD2NF , // forward to network function
} ;
struct metadata
{
uint64_t session_id ;
char * raw_data ;
int raw_len ;
int dir_is_e2i ;
int is_ctrl_pkt ;
int l7_offset ; // only control packet set l7_offset
int traffic_is_decrypted ; // only raw packet set traffic_is_decrypted
struct sids sids ;
char route_ctx [ 64 ] ;
} ;
/******************************************************************************
* API Declaration
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct packet_io * packet_io_create ( const char * profile , int thread_num ) ;
void packet_io_destory ( struct packet_io * handle ) ;
int packet_io_polling_nf_interface ( struct packet_io * handle , int thread_seq , void * ctx ) ;
int packet_io_polling_endpoint ( struct packet_io * handle , int thread_seq , void * ctx ) ;
static int packet_io_config ( const char * profile , struct config * config ) ;
// return 0 : success
// return -1 : error
static int packet_io_get_metadata ( marsio_buff_t * tx_buff , struct metadata * meta ) ;
// return 0 : success
// return -1 : error
static int packet_io_set_metadata ( marsio_buff_t * tx_buff , struct metadata * meta ) ;
// return 0 : success
// return -1 : error
static int handle_control_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx ) ;
// return : RAW_PKT_ERR_BYPASS
// return : RAW_PKT_HIT_BYPASS
// return : RAW_PKT_HIT_BLOCK
// reutrn : RAW_PKT_HIT_FORWARD
static enum raw_pkt_action handle_raw_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx ) ;
// return : INJT_PKT_ERR_DROP
// return : INJT_PKT_HIT_BLOCK
// return : INJT_PKT_HIT_FWD2SF
// return : INJT_PKT_HIT_FWD2NF
static enum inject_pkt_action handle_inject_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int forward_packet_to_sf ( struct packet_io * handle , marsio_buff_t * rx_buff , struct metadata * meta , int chain_index , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int forward_packet_to_nf ( struct packet_io * handle , marsio_buff_t * rx_buff , struct metadata * meta , int chain_index , int thread_seq , void * ct ) ;
static void forward_all_nf_packet_to_sf ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx ) ;
static void forward_all_sf_packet_to_nf ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int handle_session_opening ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int handle_session_closing ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int handle_session_active ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx ) ;
// return 0 : success
// return -1 : error
static int handle_session_resetall ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx ) ;
static void session_value_free_cb ( void * ctx ) ;
/******************************************************************************
* API Definition
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct packet_io * packet_io_create ( const char * profile , int thread_num )
{
int opt = 1 ;
struct packet_io * handle = ( struct packet_io * ) calloc ( 1 , sizeof ( struct packet_io ) ) ;
assert ( handle ! = NULL ) ;
handle - > thread_num = thread_num ;
if ( packet_io_config ( profile , & ( handle - > config ) ) ! = 0 )
{
goto error_out ;
}
handle - > instance = marsio_create ( ) ;
if ( handle - > instance = = NULL )
{
LOG_ERROR ( " %s: unable to create marsio instance " , LOG_TAG_PKTIO ) ;
goto error_out ;
}
if ( marsio_option_set ( handle - > instance , MARSIO_OPT_EXIT_WHEN_ERR , & opt , sizeof ( opt ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set MARSIO_OPT_EXIT_WHEN_ERR option for marsio instance " , LOG_TAG_PKTIO ) ;
goto error_out ;
}
if ( marsio_init ( handle - > instance , handle - > config . app_symbol ) ! = 0 )
{
LOG_ERROR ( " %s: unable to initialize marsio instance " , LOG_TAG_PKTIO ) ;
goto error_out ;
}
// Netwrok Function Interface
handle - > dev_nf_interface . mr_dev = marsio_open_device ( handle - > instance , handle - > config . dev_nf_interface , handle - > thread_num , handle - > thread_num ) ;
if ( handle - > dev_nf_interface . mr_dev = = NULL )
{
LOG_ERROR ( " %s: unable to open device %s " , LOG_TAG_PKTIO , handle - > config . dev_nf_interface ) ;
goto error_out ;
}
handle - > dev_nf_interface . mr_path = marsio_sendpath_create_by_vdev ( handle - > dev_nf_interface . mr_dev ) ;
if ( handle - > dev_nf_interface . mr_path = = NULL )
{
LOG_ERROR ( " %s: unable to create sendpath for device %s " , LOG_TAG_PKTIO , handle - > config . dev_nf_interface ) ;
goto error_out ;
}
// EndPoint Interface
handle - > dev_endpoint . mr_dev = marsio_open_device ( handle - > instance , handle - > config . dev_endpoint , handle - > thread_num , handle - > thread_num ) ;
if ( handle - > dev_endpoint . mr_dev = = NULL )
{
LOG_ERROR ( " %s: unable to open device %s " , LOG_TAG_PKTIO , handle - > config . dev_endpoint ) ;
goto error_out ;
}
handle - > dev_endpoint . mr_path = marsio_sendpath_create_by_vdev ( handle - > dev_endpoint . mr_dev ) ;
if ( handle - > dev_endpoint . mr_path = = NULL )
{
LOG_ERROR ( " %s: unable to create sendpath for device %s " , LOG_TAG_PKTIO , handle - > config . dev_endpoint ) ;
goto error_out ;
}
return handle ;
error_out :
packet_io_destory ( handle ) ;
return NULL ;
}
void packet_io_destory ( struct packet_io * handle )
{
if ( handle )
{
if ( handle - > dev_nf_interface . mr_path )
{
marsio_sendpath_destory ( handle - > dev_nf_interface . mr_path ) ;
handle - > dev_nf_interface . mr_path = NULL ;
}
if ( handle - > dev_nf_interface . mr_dev )
{
marsio_close_device ( handle - > dev_nf_interface . mr_dev ) ;
handle - > dev_nf_interface . mr_dev = NULL ;
}
if ( handle - > dev_endpoint . mr_path )
{
marsio_sendpath_destory ( handle - > dev_endpoint . mr_path ) ;
handle - > dev_endpoint . mr_path = NULL ;
}
if ( handle - > dev_endpoint . mr_dev )
{
marsio_close_device ( handle - > dev_endpoint . mr_dev ) ;
handle - > dev_endpoint . mr_dev = NULL ;
}
if ( handle - > instance )
{
marsio_destory ( handle - > instance ) ;
handle - > instance = NULL ;
}
free ( handle ) ;
handle = NULL ;
}
}
// return n_packet_recv
int packet_io_polling_nf_interface ( struct packet_io * handle , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
marsio_buff_t * rx_buffs [ RX_BURST_MAX ] ;
// nr_recv <= rx_burst_max <= RX_BURST_MAX
int nr_recv = marsio_recv_burst ( handle - > dev_nf_interface . mr_dev , thread_seq , rx_buffs , handle - > config . rx_burst_max ) ;
if ( nr_recv < = 0 )
{
return 0 ;
}
if ( handle - > config . bypass_all_traffic = = 1 )
{
for ( int j = 0 ; j < nr_recv ; j + + )
{
if ( marsio_buff_is_ctrlbuf ( rx_buffs [ j ] ) )
{
int raw_len = marsio_buff_datalen ( rx_buffs [ j ] ) ;
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_rx , 1 , raw_len ) ;
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_tx , 1 , raw_len ) ;
}
}
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , rx_buffs , nr_recv ) ;
return nr_recv ;
}
else if ( handle - > config . bypass_all_traffic = = 2 )
{
for ( int j = 0 ; j < nr_recv ; j + + )
{
marsio_buff_t * rx_buff = rx_buffs [ j ] ;
int raw_len = marsio_buff_datalen ( rx_buff ) ;
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_rx , 1 , raw_len ) ;
throughput_metrics_inc ( & g_metrics - > dev_endpoint_tx , 1 , raw_len ) ;
forward_all_nf_packet_to_sf ( handle , rx_buff , thread_seq , ctx ) ;
}
return nr_recv ;
}
for ( int j = 0 ; j < nr_recv ; j + + )
{
marsio_buff_t * rx_buff = rx_buffs [ j ] ;
if ( marsio_buff_is_ctrlbuf ( rx_buff ) )
{
handle_control_packet ( handle , rx_buff , thread_seq , ctx ) ;
// all control packet need bypass
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
}
else
{
int raw_len = marsio_buff_datalen ( rx_buff ) ;
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_rx , 1 , raw_len ) ;
enum raw_pkt_action action = handle_raw_packet ( handle , rx_buff , thread_seq , ctx ) ;
switch ( action )
{
case RAW_PKT_ERR_BYPASS :
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_err_bypass , 1 , raw_len ) ;
break ;
case RAW_PKT_HIT_BYPASS :
throughput_metrics_inc ( & g_metrics - > hit_bypass_policy , 1 , raw_len ) ;
break ;
case RAW_PKT_HIT_BLOCK :
throughput_metrics_inc ( & g_metrics - > hit_block_policy , 1 , raw_len ) ;
break ;
case RAW_PKT_HIT_FORWARD :
break ;
}
}
}
return nr_recv ;
}
// return n_packet_recv
int packet_io_polling_endpoint ( struct packet_io * handle , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
marsio_buff_t * rx_buffs [ RX_BURST_MAX ] ;
// nr_recv <= rx_burst_max <= RX_BURST_MAX
int nr_recv = marsio_recv_burst ( handle - > dev_endpoint . mr_dev , thread_seq , rx_buffs , handle - > config . rx_burst_max ) ;
if ( nr_recv < = 0 )
{
return 0 ;
}
if ( handle - > config . bypass_all_traffic = = 1 )
{
for ( int j = 0 ; j < nr_recv ; j + + )
{
int raw_len = marsio_buff_datalen ( rx_buffs [ j ] ) ;
throughput_metrics_inc ( & g_metrics - > dev_endpoint_rx , 1 , raw_len ) ;
throughput_metrics_inc ( & g_metrics - > dev_endpoint_tx , 1 , raw_len ) ;
}
marsio_send_burst ( handle - > dev_endpoint . mr_path , thread_seq , rx_buffs , nr_recv ) ;
return nr_recv ;
}
else if ( handle - > config . bypass_all_traffic = = 2 )
{
for ( int j = 0 ; j < nr_recv ; j + + )
{
marsio_buff_t * rx_buff = rx_buffs [ j ] ;
int raw_len = marsio_buff_datalen ( rx_buff ) ;
throughput_metrics_inc ( & g_metrics - > dev_endpoint_rx , 1 , raw_len ) ;
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_tx , 1 , raw_len ) ;
forward_all_sf_packet_to_nf ( handle , rx_buff , thread_seq , ctx ) ;
}
return nr_recv ;
}
for ( int j = 0 ; j < nr_recv ; j + + )
{
marsio_buff_t * rx_buff = rx_buffs [ j ] ;
int data_len = marsio_buff_datalen ( rx_buff ) ;
throughput_metrics_inc ( & g_metrics - > dev_endpoint_rx , 1 , data_len ) ;
enum inject_pkt_action action = handle_inject_packet ( handle , rx_buff , thread_seq , ctx ) ;
switch ( action )
{
case INJT_PKT_ERR_DROP :
throughput_metrics_inc ( & g_metrics - > dev_endpoint_err_drop , 1 , data_len ) ;
break ;
case INJT_PKT_HIT_BLOCK :
throughput_metrics_inc ( & g_metrics - > hit_block_policy , 1 , data_len ) ;
break ;
case INJT_PKT_HIT_FWD2SF : // forward to next service function
throughput_metrics_inc ( & g_metrics - > dev_endpoint_tx , 1 , data_len ) ;
break ;
case INJT_PKT_HIT_FWD2NF : // forward to network function
throughput_metrics_inc ( & g_metrics - > dev_nf_interface_tx , 1 , data_len ) ;
break ;
}
}
return nr_recv ;
}
// return -1 : error
// return 0 : success
static int packet_io_config ( const char * profile , struct config * config )
{
MESA_load_profile_int_def ( profile , " PACKET_IO " , " bypass_all_traffic " , ( int * ) & ( config - > bypass_all_traffic ) , 0 ) ;
MESA_load_profile_int_def ( profile , " PACKET_IO " , " rx_burst_max " , ( int * ) & ( config - > rx_burst_max ) , 1 ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " app_symbol " , config - > app_symbol , sizeof ( config - > app_symbol ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " dev_endpoint " , config - > dev_endpoint , sizeof ( config - > dev_endpoint ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " dev_nf_interface " , config - > dev_nf_interface , sizeof ( config - > dev_nf_interface ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " default_src_ip " , config - > default_src_ip , sizeof ( config - > default_src_ip ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " default_dst_ip " , config - > default_dst_ip , sizeof ( config - > default_dst_ip ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " default_src_mac " , config - > default_src_mac , sizeof ( config - > default_src_mac ) ) ;
MESA_load_profile_string_nodef ( profile , " PACKET_IO " , " default_dst_mac " , config - > default_dst_mac , sizeof ( config - > default_dst_mac ) ) ;
if ( config - > rx_burst_max > RX_BURST_MAX )
{
LOG_ERROR ( " %s: invalid rx_burst_max, exceeds limit %d " , LOG_TAG_PKTIO , RX_BURST_MAX ) ;
return - 1 ;
}
if ( strlen ( config - > app_symbol ) = = 0 )
{
LOG_ERROR ( " %s: invalid app_symbol in %s " , LOG_TAG_PKTIO , profile ) ;
return - 1 ;
}
if ( strlen ( config - > dev_endpoint ) = = 0 )
{
LOG_ERROR ( " %s: invalid dev_endpoint in %s " , LOG_TAG_PKTIO , profile ) ;
return - 1 ;
}
if ( strlen ( config - > dev_nf_interface ) = = 0 )
{
LOG_ERROR ( " %s: invalid dev_nf_interface in %s " , LOG_TAG_PKTIO , profile ) ;
return - 1 ;
}
LOG_DEBUG ( " %s: PACKET_IO->bypass_all_traffic : %d " , LOG_TAG_PKTIO , config - > bypass_all_traffic ) ;
LOG_DEBUG ( " %s: PACKET_IO->rx_burst_max : %d " , LOG_TAG_PKTIO , config - > rx_burst_max ) ;
LOG_DEBUG ( " %s: PACKET_IO->app_symbol : %s " , LOG_TAG_PKTIO , config - > app_symbol ) ;
LOG_DEBUG ( " %s: PACKET_IO->dev_endpoint : %s " , LOG_TAG_PKTIO , config - > dev_endpoint ) ;
LOG_DEBUG ( " %s: PACKET_IO->dev_nf_interface : %s " , LOG_TAG_PKTIO , config - > dev_nf_interface ) ;
LOG_DEBUG ( " %s: PACKET_IO->default_src_ip : %s " , LOG_TAG_PKTIO , config - > default_src_ip ) ;
LOG_DEBUG ( " %s: PACKET_IO->default_dst_ip : %s " , LOG_TAG_PKTIO , config - > default_dst_ip ) ;
LOG_DEBUG ( " %s: PACKET_IO->default_src_mac : %s " , LOG_TAG_PKTIO , config - > default_src_mac ) ;
LOG_DEBUG ( " %s: PACKET_IO->default_dst_mac : %s " , LOG_TAG_PKTIO , config - > default_dst_mac ) ;
return 0 ;
}
// return 0 : success
// return -1 : error
static int packet_io_get_metadata ( marsio_buff_t * rx_buff , struct metadata * meta )
{
memset ( meta , 0 , sizeof ( struct metadata ) ) ;
if ( marsio_buff_get_metadata ( rx_buff , MR_BUFF_SESSION_ID , & ( meta - > session_id ) , sizeof ( meta - > session_id ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to get session_id from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
meta - > raw_len = marsio_buff_datalen ( rx_buff ) ;
meta - > raw_data = marsio_buff_mtod ( rx_buff ) ;
if ( meta - > raw_data = = NULL | | meta - > raw_len = = 0 )
{
LOG_ERROR ( " %s: unable to get raw_data from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
// 1: E2I
// 0: I2E
if ( marsio_buff_get_metadata ( rx_buff , MR_BUFF_DIR , & ( meta - > dir_is_e2i ) , sizeof ( meta - > dir_is_e2i ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to get buff_dir from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
if ( marsio_buff_is_ctrlbuf ( rx_buff ) )
{
meta - > is_ctrl_pkt = 1 ;
// only control packet set MR_L7_OFFSET
// TODO
#if 0
if ( marsio_buff_get_metadata ( rx_buff , MR_L7_OFFSET , & ( meta - > l7_offset ) , sizeof ( meta - > l7_offset ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to get l7_offset from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
# endif
}
else
{
meta - > is_ctrl_pkt = 0 ;
// only raw packet set MR_IS_DECRYPTED
// TODO
#if 0
if ( marsio_buff_get_metadata ( rx_buff , MR_IS_DECRYPTED , & ( meta - > traffic_is_decrypted ) , sizeof ( meta - > traffic_is_decrypted ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to get traffic_is_decrypted from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
# endif
}
if ( marsio_buff_get_metadata ( rx_buff , MR_BUFF_ROUTE_CTX , meta - > route_ctx , sizeof ( meta - > route_ctx ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to get route_ctx from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
meta - > sids . num = marsio_buff_get_sid_list ( rx_buff , meta - > sids . elems , sizeof ( meta - > sids . elems ) / sizeof ( meta - > sids . elems [ 0 ] ) ) ;
if ( meta - > sids . num < = 0 )
{
LOG_ERROR ( " %s: unable to get sid_list from metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
return 0 ;
}
// return 0 : success
// return -1 : error
static int packet_io_set_metadata ( marsio_buff_t * tx_buff , struct metadata * meta )
{
if ( meta - > session_id )
{
if ( marsio_buff_set_metadata ( tx_buff , MR_BUFF_SESSION_ID , & ( meta - > session_id ) , sizeof ( meta - > session_id ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set session_id for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
}
// 1: E2I
// 0: I2E
if ( marsio_buff_set_metadata ( tx_buff , MR_BUFF_DIR , & ( meta - > dir_is_e2i ) , sizeof ( meta - > dir_is_e2i ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set buff_dir for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
if ( meta - > is_ctrl_pkt )
{
// TODO
#if 0
if ( marsio_buff_set_metadata ( tx_buff , MR_L7_OFFSET , & ( meta - > l7_offset ) , sizeof ( meta - > l7_offset ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set l7_offset for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
# endif
}
else
{
// TODO
#if 0
if ( marsio_buff_set_metadata ( tx_buff , MR_IS_DECRYPTED , & ( meta - > traffic_is_decrypted ) , sizeof ( meta - > traffic_is_decrypted ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set traffic_is_decrypted for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
# endif
}
if ( strlen ( meta - > route_ctx ) )
{
if ( marsio_buff_set_metadata ( tx_buff , MR_BUFF_ROUTE_CTX , meta - > route_ctx , sizeof ( meta - > route_ctx ) ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set route_ctx for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
}
if ( meta - > sids . num )
{
if ( marsio_buff_set_sid_list ( tx_buff , meta - > sids . elems , meta - > sids . num ) ! = 0 )
{
LOG_ERROR ( " %s: unable to set sid_list for metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
}
return 0 ;
}
// return 0 : success
// return -1 : error
static int handle_control_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx )
{
struct metadata meta ;
if ( packet_io_get_metadata ( rx_buff , & meta ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected control packet, unable to get metadata " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
struct ctrl_pkt_parser ctrl_parser ;
ctrl_packet_parser_init ( & ctrl_parser ) ;
if ( ctrl_packet_parser_parse ( & ctrl_parser , meta . raw_data + meta . l7_offset , meta . raw_len - meta . l7_offset ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected control packet, unable to parse data " , LOG_TAG_PKTIO ) ;
return - 1 ;
}
if ( ctrl_parser . session_id ! = meta . session_id )
{
LOG_ERROR ( " %s: unexpected control packet, metadata's session %lu != control packet's session %lu " , LOG_TAG_PKTIO , meta . session_id , ctrl_parser . session_id ) ;
return - 1 ;
}
switch ( ctrl_parser . state )
{
case SESSION_STATE_OPENING :
// when session opening, firewall not send policy id
// return handle_session_opening(&meta, &ctrl_parser, thread_seq, ctx);
break ;
case SESSION_STATE_CLONING :
return handle_session_closing ( & meta , & ctrl_parser , thread_seq , ctx ) ;
case SESSION_STATE_ACTIVE :
return handle_session_active ( & meta , & ctrl_parser , thread_seq , ctx ) ;
case SESSION_STATE_RESETALL :
return handle_session_resetall ( & meta , & ctrl_parser , thread_seq , ctx ) ;
}
return 0 ;
}
// return : RAW_PKT_ERR_BYPASS
// return : RAW_PKT_HIT_BYPASS
// return : RAW_PKT_HIT_BLOCK
// reutrn : RAW_PKT_HIT_FORWARD
static enum raw_pkt_action handle_raw_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct metadata meta ;
if ( packet_io_get_metadata ( rx_buff , & meta ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected raw packet, unable to get metadata, bypass !!! " , LOG_TAG_PKTIO ) ;
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_ERR_BYPASS ;
}
struct session_node * node = session_table_search_by_id ( thread - > session_table , meta . session_id ) ;
if ( node = = NULL )
{
LOG_ERROR ( " %s: unexpected raw packet, unable to find session %lu from session table, bypass !!! " , LOG_TAG_PKTIO , meta . session_id ) ;
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_ERR_BYPASS ;
}
// update sids
struct session_ctx * s_ctx = ( struct session_ctx * ) node - > val_data ;
if ( meta . dir_is_e2i )
{
sids_write_once ( & ( s_ctx - > raw_pkt_e2i_sids ) , & ( meta . sids ) ) ;
if ( ! strlen ( s_ctx - > raw_pkt_e2i_route_ctx ) )
{
memcpy ( s_ctx - > raw_pkt_e2i_route_ctx , meta . route_ctx , sizeof ( s_ctx - > raw_pkt_e2i_route_ctx ) ) ;
}
}
else
{
sids_write_once ( & ( s_ctx - > raw_pkt_i2e_sids ) , & ( meta . sids ) ) ;
if ( ! strlen ( s_ctx - > raw_pkt_i2e_route_ctx ) )
{
memcpy ( s_ctx - > raw_pkt_i2e_route_ctx , meta . route_ctx , sizeof ( s_ctx - > raw_pkt_i2e_route_ctx ) ) ;
}
}
// search chaining
struct selected_chaining * chaining = s_ctx - > chaining ;
if ( chaining = = NULL )
{
LOG_ERROR ( " %s: unexpected raw packet, session %lu %s misses policy, bypass !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_ERR_BYPASS ;
}
for ( int i = 0 ; i < chaining - > chaining_size ; i + + )
{
struct selected_sf * node = & ( chaining - > chaining [ i ] ) ;
LOG_INFO ( " %s: session %lu %s execute policy: %d -> sff_profile_id %d -> sf_profile_id %d -> sf_need_skip %d sf_action_reason : %d " ,
LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string , node - > policy_id , node - > sff_profile_id , node - > sf_profile_id , node - > sf_need_skip , node - > sf_action_reason ) ;
if ( node - > sf_need_skip )
{
continue ;
}
switch ( node - > sf_action )
{
case SESSION_ACTION_BYPASS :
// BYPASS CURRENT SF
continue ;
case SESSION_ACTION_BLOCK :
// BLOCK ALL SF
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return RAW_PKT_HIT_BLOCK ;
case SESSION_ACTION_FORWARD :
if ( node - > sf_connectivity . method ! = PACKAGE_METHOD_VXLAN_G )
{
LOG_ERROR ( " %s: processing raw packets, session %lu %s requires encapsulation format not supported, bypass !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_ERR_BYPASS ;
}
if ( forward_packet_to_sf ( handle , rx_buff , & meta , i + 1 , thread_seq , ctx ) = = 0 )
{
throughput_metrics_inc ( & node - > tx , 1 , meta . raw_len ) ;
return RAW_PKT_HIT_FORWARD ;
}
else
{
LOG_ERROR ( " %s: processing raw packet, session %lu %s forwarding packet to service function failed, bypass !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
// TODO
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_ERR_BYPASS ;
}
default :
continue ;
}
}
// BYPASS ALL SF
LOG_INFO ( " %s: session %lu %s bypass all service function " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ;
return RAW_PKT_HIT_BYPASS ;
}
// return : INJT_PKT_ERR_DROP
// return : INJT_PKT_HIT_BLOCK
// return : INJT_PKT_HIT_FWD2SF
// return : INJT_PKT_HIT_FWD2NF
static enum inject_pkt_action handle_inject_packet ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct g_vxlan * g_vxlan_hdr = NULL ;
int raw_len = marsio_buff_datalen ( rx_buff ) ;
char * raw_data = marsio_buff_mtod ( rx_buff ) ;
if ( g_vxlan_decode ( & g_vxlan_hdr , raw_data , raw_len ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected inject packet, not a vxlan-encapsulated packet, drop !!! " , LOG_TAG_PKTIO ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
struct metadata meta ;
memset ( & meta , 0 , sizeof ( struct metadata ) ) ;
meta . raw_data = ( char * ) g_vxlan_hdr + sizeof ( struct g_vxlan ) ;
meta . raw_len = raw_len - sizeof ( struct ethhdr ) - sizeof ( struct ip ) - sizeof ( struct udphdr ) - sizeof ( struct g_vxlan ) ;
meta . dir_is_e2i = g_vxlan_get_packet_dir ( g_vxlan_hdr ) ;
meta . traffic_is_decrypted = g_vxlan_get_traffic_type ( g_vxlan_hdr ) ;
meta . is_ctrl_pkt = 0 ;
meta . l7_offset = 0 ;
// meta.session_id set later
// meta.sids set later
int chain_index = g_vxlan_get_chain_index ( g_vxlan_hdr ) ;
struct addr_tuple4 inner_addr ;
struct raw_pkt_parser raw_parser ;
memset ( & inner_addr , 0 , sizeof ( struct addr_tuple4 ) ) ;
raw_packet_parser_init ( & raw_parser , 0 , LAYER_TYPE_ALL , 8 ) ;
raw_packet_parser_parse ( & raw_parser , ( const void * ) meta . raw_data , meta . raw_len ) ;
raw_packet_parser_get_most_inner_tuple4 ( & raw_parser , & inner_addr ) ;
struct session_node * node = session_table_search_by_addr ( thread - > session_table , & inner_addr ) ;
if ( node = = NULL )
{
char * addr_string = addr_tuple4_to_str ( & inner_addr ) ;
LOG_ERROR ( " %s: unexpected inject packet, unable to find session %s from session table, drop !!! " , LOG_TAG_PKTIO , addr_string ) ;
free ( addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
struct session_ctx * s_ctx = ( struct session_ctx * ) node - > val_data ;
meta . session_id = s_ctx - > session_id ;
if ( meta . dir_is_e2i )
{
sids_copy ( & meta . sids , & s_ctx - > raw_pkt_e2i_sids ) ;
memcpy ( meta . route_ctx , s_ctx - > raw_pkt_e2i_route_ctx , sizeof ( s_ctx - > raw_pkt_e2i_route_ctx ) ) ;
}
else
{
sids_copy ( & meta . sids , & s_ctx - > raw_pkt_i2e_sids ) ;
memcpy ( meta . route_ctx , s_ctx - > raw_pkt_i2e_route_ctx , sizeof ( s_ctx - > raw_pkt_i2e_route_ctx ) ) ;
}
struct selected_chaining * chaining = s_ctx - > chaining ;
if ( chaining = = NULL | | chain_index < 1 | | chain_index > chaining - > chaining_size )
{
LOG_ERROR ( " %s: unexpected inject packet, session %lu %s misses chaining index, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
throughput_metrics_inc ( & chaining - > chaining [ chain_index - 1 ] . rx , 1 , meta . raw_len ) ;
for ( int i = chain_index ; i < chaining - > chaining_size ; i + + )
{
struct selected_sf * node = & ( chaining - > chaining [ i ] ) ;
LOG_INFO ( " %s: session %lu %s execute policy: %d -> sff_profile_id %d -> sf_profile_id %d -> sf_need_skip %d sf_action_reason : %d " ,
LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string , node - > policy_id , node - > sff_profile_id , node - > sf_profile_id , node - > sf_need_skip , node - > sf_action_reason ) ;
if ( node - > sf_need_skip )
{
continue ;
}
switch ( node - > sf_action )
{
case SESSION_ACTION_BYPASS :
// BYPASS CURRENT SF
continue ;
case SESSION_ACTION_BLOCK :
// BLOCK ALL SF
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_HIT_BLOCK ;
case SESSION_ACTION_FORWARD :
if ( node - > sf_connectivity . method ! = PACKAGE_METHOD_VXLAN_G )
{
LOG_ERROR ( " %s: processing inject packets, session %lu %s requires encapsulation format not supported, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
if ( forward_packet_to_sf ( handle , rx_buff , & meta , i + 1 , thread_seq , ctx ) = = 0 )
{
throughput_metrics_inc ( & node - > tx , 1 , meta . raw_len ) ;
return INJT_PKT_HIT_FWD2SF ;
}
else
{
LOG_ERROR ( " %s: processing inject packet, session %lu %s forwarding packet to service function failed, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
default :
continue ;
}
}
if ( chain_index ! = chaining - > chaining_size )
{
LOG_ERROR ( " %s: unexpected inject packet, session %lu %s using invalid chaining index, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
if ( forward_packet_to_nf ( handle , rx_buff , & meta , - 1 , thread_seq , ctx ) = = - 1 )
{
LOG_ERROR ( " %s: processing inject packet, session %lu %s forwarding packet to network function failed, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return INJT_PKT_ERR_DROP ;
}
else
{
return INJT_PKT_HIT_FWD2NF ;
}
}
// return 0 : success
// return -1 : error
static int forward_packet_to_sf ( struct packet_io * handle , marsio_buff_t * rx_buff , struct metadata * meta , int chain_index , int thread_seq , void * ctx )
{
// TODO get dst ip frome policy
// TODO get dst mac by dst ip
marsio_buff_reset ( rx_buff ) ;
struct ethhdr * eth_hdr = ( struct ethhdr * ) marsio_buff_prepend ( rx_buff , sizeof ( struct ethhdr ) + sizeof ( struct ip ) + sizeof ( struct udphdr ) + sizeof ( struct g_vxlan ) ) ;
struct ip * ip_hdr = ( struct ip * ) ( ( char * ) eth_hdr + sizeof ( struct ethhdr ) ) ;
struct udphdr * udp_hdr = ( struct udphdr * ) ( ( char * ) ip_hdr + sizeof ( struct ip ) ) ;
struct g_vxlan * g_vxlan_hdr = ( struct g_vxlan * ) ( ( char * ) udp_hdr + sizeof ( struct udphdr ) ) ;
memset ( g_vxlan_hdr , 0 , sizeof ( struct g_vxlan ) ) ;
g_vxlan_set_packet_dir ( g_vxlan_hdr , meta - > dir_is_e2i ) ;
g_vxlan_set_chain_index ( g_vxlan_hdr , chain_index ) ;
g_vxlan_set_traffic_type ( g_vxlan_hdr , meta - > traffic_is_decrypted ) ;
build_ether_header ( eth_hdr , ETH_P_IP , handle - > config . default_src_mac , handle - > config . default_dst_mac ) ;
build_ip_header ( ip_hdr , IPPROTO_UDP , handle - > config . default_src_ip , handle - > config . default_dst_ip , sizeof ( struct udphdr ) + sizeof ( struct g_vxlan ) + meta - > raw_len ) ;
build_udp_header ( ( const char * ) & ip_hdr - > ip_src , 8 , udp_hdr , meta - > session_id % ( 65535 - 49152 ) + 49152 , 4789 , sizeof ( struct g_vxlan ) + meta - > raw_len ) ;
if ( marsio_send_burst ( handle - > dev_endpoint . mr_path , thread_seq , & rx_buff , 1 ) ! = 0 )
{
LOG_ERROR ( " %s: unable to send burst on device %s, thread_seq: %d " , LOG_TAG_PKTIO , handle - > config . dev_endpoint , thread_seq ) ;
return - 1 ;
}
return 0 ;
}
// return 0 : success
// return -1 : error
static int forward_packet_to_nf ( struct packet_io * handle , marsio_buff_t * rx_buff , struct metadata * meta , int chain_index , int thread_seq , void * ct )
{
marsio_buff_adj ( rx_buff , marsio_buff_datalen ( rx_buff ) - meta - > raw_len ) ;
marsio_buff_reset ( rx_buff ) ;
if ( packet_io_set_metadata ( rx_buff , meta ) ! = 0 )
{
return - 1 ;
}
if ( marsio_send_burst ( handle - > dev_nf_interface . mr_path , thread_seq , & rx_buff , 1 ) ! = 0 )
{
LOG_ERROR ( " %s: unable to send burst on device %s, thread_seq: %d " , LOG_TAG_PKTIO , handle - > config . dev_nf_interface , thread_seq ) ;
return - 1 ;
}
return 0 ;
}
static void forward_all_nf_packet_to_sf ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
struct metadata meta ;
struct raw_pkt_parser raw_parser ;
struct addr_tuple4 inner_tuple4 ;
struct session_ctx * s_ctx = NULL ;
struct session_node * node = NULL ;
const void * payload = NULL ;
// get metadata
if ( packet_io_get_metadata ( rx_buff , & meta ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected raw packet, unable to get metadata, drop !!! " , LOG_TAG_PKTIO ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return ;
}
// search session id
node = session_table_search_by_id ( thread - > session_table , meta . session_id ) ;
if ( node )
{
goto forward ;
}
// add to session table
raw_packet_parser_init ( & raw_parser , meta . session_id , LAYER_TYPE_ALL , 8 ) ;
payload = raw_packet_parser_parse ( & raw_parser , ( const void * ) meta . raw_data , meta . raw_len ) ;
if ( ( char * ) payload - ( char * ) & meta . raw_data ! = meta . l7_offset )
{
LOG_ERROR ( " %s: incorrect dataoffset in the control zone of session %lu " , LOG_TAG_PKTIO , meta . session_id ) ;
}
s_ctx = session_ctx_new ( ) ;
s_ctx - > session_id = meta . session_id ;
s_ctx - > first_ctrl_pkt . dir_is_e2i = meta . dir_is_e2i ;
raw_packet_parser_get_most_inner_tuple4 ( & raw_parser , & inner_tuple4 ) ;
s_ctx - > first_ctrl_pkt . addr_string = addr_tuple4_to_str ( & inner_tuple4 ) ;
if ( meta . dir_is_e2i )
{
sids_write_once ( & ( s_ctx - > raw_pkt_e2i_sids ) , & ( meta . sids ) ) ;
if ( ! strlen ( s_ctx - > raw_pkt_e2i_route_ctx ) )
{
memcpy ( s_ctx - > raw_pkt_e2i_route_ctx , meta . route_ctx , sizeof ( s_ctx - > raw_pkt_e2i_route_ctx ) ) ;
}
}
else
{
sids_write_once ( & ( s_ctx - > raw_pkt_i2e_sids ) , & ( meta . sids ) ) ;
if ( ! strlen ( s_ctx - > raw_pkt_i2e_route_ctx ) )
{
memcpy ( s_ctx - > raw_pkt_i2e_route_ctx , meta . route_ctx , sizeof ( s_ctx - > raw_pkt_i2e_route_ctx ) ) ;
}
}
LOG_INFO ( " %s: session %lu %s opening " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
// TODO only add session
__atomic_fetch_add ( & g_metrics - > session_nums , 1 , __ATOMIC_RELAXED ) ;
session_table_insert ( thread - > session_table , s_ctx - > session_id , & inner_tuple4 , s_ctx , session_value_free_cb ) ;
// forward data
forward :
if ( forward_packet_to_sf ( handle , rx_buff , & meta , 0 , thread_seq , ctx ) = = 0 )
{
LOG_ERROR ( " %s: processing raw packet, session %lu %s forwarding packet to service function failed, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return ;
}
}
static void forward_all_sf_packet_to_nf ( struct packet_io * handle , marsio_buff_t * rx_buff , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
// vxlan decode
struct g_vxlan * g_vxlan_hdr = NULL ;
int raw_len = marsio_buff_datalen ( rx_buff ) ;
char * raw_data = marsio_buff_mtod ( rx_buff ) ;
if ( g_vxlan_decode ( & g_vxlan_hdr , raw_data , raw_len ) = = - 1 )
{
LOG_ERROR ( " %s: unexpected inject packet, not a vxlan-encapsulated packet, drop !!! " , LOG_TAG_PKTIO ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return ;
}
struct metadata meta ;
memset ( & meta , 0 , sizeof ( struct metadata ) ) ;
meta . raw_data = ( char * ) g_vxlan_hdr + sizeof ( struct g_vxlan ) ;
meta . raw_len = raw_len - sizeof ( struct ethhdr ) - sizeof ( struct ip ) - sizeof ( struct udphdr ) - sizeof ( struct g_vxlan ) ;
meta . dir_is_e2i = g_vxlan_get_packet_dir ( g_vxlan_hdr ) ;
meta . traffic_is_decrypted = g_vxlan_get_traffic_type ( g_vxlan_hdr ) ;
meta . is_ctrl_pkt = 0 ;
meta . l7_offset = 0 ;
// get inner tuple4
struct addr_tuple4 inner_addr ;
struct raw_pkt_parser raw_parser ;
memset ( & inner_addr , 0 , sizeof ( struct addr_tuple4 ) ) ;
raw_packet_parser_init ( & raw_parser , 0 , LAYER_TYPE_ALL , 8 ) ;
raw_packet_parser_parse ( & raw_parser , ( const void * ) meta . raw_data , meta . raw_len ) ;
raw_packet_parser_get_most_inner_tuple4 ( & raw_parser , & inner_addr ) ;
// search session table
struct session_node * node = session_table_search_by_addr ( thread - > session_table , & inner_addr ) ;
if ( node = = NULL )
{
char * addr_string = addr_tuple4_to_str ( & inner_addr ) ;
LOG_ERROR ( " %s: unexpected inject packet, unable to find session %s from session table, drop !!! " , LOG_TAG_PKTIO , addr_string ) ;
free ( addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return ;
}
// add meta data
struct session_ctx * s_ctx = ( struct session_ctx * ) node - > val_data ;
meta . session_id = s_ctx - > session_id ;
if ( meta . dir_is_e2i )
{
sids_copy ( & meta . sids , & s_ctx - > raw_pkt_e2i_sids ) ;
memcpy ( meta . route_ctx , s_ctx - > raw_pkt_e2i_route_ctx , sizeof ( s_ctx - > raw_pkt_e2i_route_ctx ) ) ;
}
else
{
sids_copy ( & meta . sids , & s_ctx - > raw_pkt_i2e_sids ) ;
memcpy ( meta . route_ctx , s_ctx - > raw_pkt_i2e_route_ctx , sizeof ( s_ctx - > raw_pkt_i2e_route_ctx ) ) ;
}
// sendto nf
if ( forward_packet_to_nf ( handle , rx_buff , & meta , - 1 , thread_seq , ctx ) = = - 1 )
{
LOG_ERROR ( " %s: processing inject packet, session %lu %s forwarding packet to network function failed, drop !!! " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
marsio_buff_free ( handle - > instance , & rx_buff , 1 , 0 , thread_seq ) ;
return ;
}
}
// return 0 : success
// return -1 : error
static int handle_session_opening ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
if ( session_table_search_by_id ( thread - > session_table , meta - > session_id ) )
{
return - 1 ;
}
struct raw_pkt_parser raw_parser ;
raw_packet_parser_init ( & raw_parser , meta - > session_id , LAYER_TYPE_ALL , 8 ) ;
const void * payload = raw_packet_parser_parse ( & raw_parser , ( const void * ) meta - > raw_data , meta - > raw_len ) ;
if ( ( char * ) payload - ( char * ) & meta - > raw_data ! = meta - > l7_offset )
{
LOG_ERROR ( " %s: incorrect dataoffset in the control zone of session %lu " , LOG_TAG_PKTIO , meta - > session_id ) ;
}
struct session_ctx * s_ctx = session_ctx_new ( ) ;
fixed_num_array_init ( & s_ctx - > policy_ids ) ;
s_ctx - > session_id = meta - > session_id ;
s_ctx - > first_ctrl_pkt . dir_is_e2i = meta - > dir_is_e2i ;
raw_packet_parser_get_most_inner_tuple4 ( & raw_parser , & ( s_ctx - > first_ctrl_pkt . tuple4 ) ) ;
s_ctx - > first_ctrl_pkt . addr_string = addr_tuple4_to_str ( & ( s_ctx - > first_ctrl_pkt . tuple4 ) ) ;
s_ctx - > first_ctrl_pkt . header_data = strndup ( meta - > raw_data , meta - > l7_offset ) ;
s_ctx - > first_ctrl_pkt . header_len = meta - > l7_offset ;
s_ctx - > chaining = selected_chaining_create ( 128 ) ;
for ( int i = 0 ; i < parser - > policy_id_num ; i + + )
{
int new_policy_id = parser - > policy_ids [ i ] ;
if ( fixed_num_array_exist_elem ( & s_ctx - > policy_ids , new_policy_id ) )
{
continue ;
}
else
{
policy_enforce_select_chaining ( s_ctx - > chaining , thread - > ref_enforcer , & raw_parser , new_policy_id , meta - > dir_is_e2i ) ;
fixed_num_array_add_elem ( & s_ctx - > policy_ids , new_policy_id ) ;
}
}
LOG_INFO ( " %s: session %lu %s opening " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
__atomic_fetch_add ( & g_metrics - > session_nums , 1 , __ATOMIC_RELAXED ) ;
session_table_insert ( thread - > session_table , s_ctx - > session_id , & ( s_ctx - > first_ctrl_pkt . tuple4 ) , s_ctx , session_value_free_cb ) ;
return 0 ;
}
// return 0 : success
// return -1 : error
static int handle_session_closing ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
struct session_node * node = session_table_search_by_id ( thread - > session_table , meta - > session_id ) ;
if ( node )
{
struct session_ctx * s_ctx = ( struct session_ctx * ) node - > val_data ;
LOG_INFO ( " %s: session %lu %s closing " , LOG_TAG_PKTIO , s_ctx - > session_id , s_ctx - > first_ctrl_pkt . addr_string ) ;
// TODO send log to firewall
__atomic_fetch_sub ( & g_metrics - > session_nums , 1 , __ATOMIC_RELAXED ) ;
session_table_delete_by_id ( thread - > session_table , meta - > session_id ) ;
return 0 ;
}
return - 1 ;
}
// return 0 : success
// return -1 : error
static int handle_session_active ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
struct session_node * node = session_table_search_by_id ( thread - > session_table , meta - > session_id ) ;
if ( node )
{
struct raw_pkt_parser raw_parser ;
raw_packet_parser_init ( & raw_parser , meta - > session_id , LAYER_TYPE_ALL , 8 ) ;
const void * payload = raw_packet_parser_parse ( & raw_parser , ( const void * ) meta - > raw_data , meta - > raw_len ) ;
if ( ( char * ) payload - ( char * ) & meta - > raw_data ! = meta - > l7_offset )
{
LOG_ERROR ( " %s: incorrect dataoffset in the control zone of session %lu " , LOG_TAG_PKTIO , meta - > session_id ) ;
}
struct session_ctx * s_ctx = ( struct session_ctx * ) node - > val_data ;
for ( int i = 0 ; i < parser - > policy_id_num ; i + + )
{
int new_policy_id = parser - > policy_ids [ i ] ;
if ( fixed_num_array_exist_elem ( & s_ctx - > policy_ids , new_policy_id ) )
{
continue ;
}
else
{
policy_enforce_select_chaining ( s_ctx - > chaining , thread - > ref_enforcer , & raw_parser , new_policy_id , meta - > dir_is_e2i ) ;
fixed_num_array_add_elem ( & s_ctx - > policy_ids , new_policy_id ) ;
}
}
}
else
{
return handle_session_opening ( meta , parser , thread_seq , ctx ) ;
}
return 0 ;
}
// return 0 : success
// return -1 : error
static int handle_session_resetall ( struct metadata * meta , struct ctrl_pkt_parser * parser , int thread_seq , void * ctx )
{
struct thread_ctx * thread = ( struct thread_ctx * ) ctx ;
struct global_metrics * g_metrics = thread - > ref_metrics ;
2023-02-17 17:45:39 +08:00
struct sce_ctx * sce_ctx = thread - > ref_sce_ctx ;
2023-02-10 14:22:40 +08:00
LOG_ERROR ( " %s: session %lu notification clears all session tables !!! " , LOG_TAG_PKTIO , meta - > session_id ) ;
__atomic_fetch_and ( & g_metrics - > session_nums , 0 , __ATOMIC_RELAXED ) ;
2023-02-17 17:45:39 +08:00
for ( int i = 0 ; i < sce_ctx - > nr_worker_threads ; i + + )
{
struct thread_ctx * thread_ctx = & sce_ctx - > work_threads [ i ] ;
__atomic_fetch_add ( & thread_ctx - > session_table_need_reset , 1 , __ATOMIC_RELAXED ) ;
}
2023-02-10 14:22:40 +08:00
return 0 ;
}
static void session_value_free_cb ( void * ctx )
{
struct session_ctx * s_ctx = ( struct session_ctx * ) ctx ;
session_ctx_free ( s_ctx ) ;
}