@ -22,55 +22,21 @@
* \ author Phil Young < py @ napatech . com >
*
*
*/
*/
# include "suricata-common.h"
# ifdef HAVE_NAPATECH
# include "suricata.h"
# include "util-device.h"
# include "util-cpu.h"
# include "threadvars.h"
# include "tm-threads.h"
uint16_t NapatechGetNumaNode ( uint16_t stream_id )
{
int status ;
char buffer [ 80 ] ; // Error buffer
NtInfoStream_t info_stream ;
NtInfo_t info ;
uint16_t numa_node ;
if ( ( status = NT_InfoOpen ( & info_stream , " SuricataStreamInfo " ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , buffer , sizeof ( buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , " NT_InfoOpen failed: %s " , buffer ) ;
exit ( EXIT_FAILURE ) ;
}
// Read the info on this specific stream
info . cmd = NT_INFO_CMD_READ_STREAMID ;
info . u . streamID . streamId = stream_id ;
if ( ( status = NT_InfoRead ( info_stream , & info ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , buffer , sizeof ( buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoRead() failed: %s \n " , buffer ) ;
exit ( EXIT_FAILURE ) ;
}
numa_node = info . u . streamID . data . numaNode ;
if ( ( status = NT_InfoClose ( info_stream ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , buffer , sizeof ( buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , " NT_InfoClose failed: %s " , buffer ) ;
exit ( EXIT_FAILURE ) ;
}
return numa_node ;
}
/*-----------------------------------------------------------------------------
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Statistics code
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
typedef struct StreamCounters_ {
uint16_t pkts ;
@ -87,6 +53,13 @@ NapatechCurrentStats NapatechGetCurrentStats(uint16_t id)
return current_stats [ id ] ;
}
enum CONFIG_SPECIFIER {
CONFIG_SPECIFIER_UNDEFINED = 0 ,
CONFIG_SPECIFIER_RANGE ,
CONFIG_SPECIFIER_INDIVIDUAL
} ;
# define MAX_HOSTBUFFERS 8
static uint16_t TestStreamConfig (
NtInfoStream_t hInfo ,
@ -112,7 +85,8 @@ static uint16_t TestStreamConfig(
if ( ( status = NT_StatRead ( hStatStream , & stat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , buffer , sizeof ( buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatRead():2 failed: %s \n " , buffer ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatRead():2 failed: %s \n " , buffer ) ;
return 0 ;
}
@ -148,12 +122,14 @@ static uint32_t UpdateStreamStats(ThreadVars *tv,
hStreamInfo . cmd = NT_INFO_CMD_READ_STREAM ;
if ( ( status = NT_InfoRead ( hInfo , & hStreamInfo ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoRead() failed: %s \n " , error_buffer ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_InfoRead() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
uint16_t num_active ;
if ( ( num_active = TestStreamConfig ( hInfo , hStatStream , stream_config , num_streams ) ) = = 0 ) {
if ( ( num_active = TestStreamConfig ( hInfo , hStatStream ,
stream_config , num_streams ) ) = = 0 ) {
/* None of the configured streams are active */
return 0 ;
}
@ -164,7 +140,7 @@ static uint32_t UpdateStreamStats(ThreadVars *tv,
for ( stream_cnt = 0 ; stream_cnt < num_streams ; + + stream_cnt ) {
while ( inst_id < num_streams ) {
while ( inst_id < num_streams ) {
if ( stream_config [ inst_id ] . is_active ) {
break ;
} else {
@ -182,7 +158,8 @@ static uint32_t UpdateStreamStats(ThreadVars *tv,
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatRead() failed: %s \n " , error_buffer ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatRead() failed: %s \n " , error_buffer ) ;
return 0 ;
}
@ -249,7 +226,8 @@ static void *NapatechStatsLoop(void *arg)
for ( int i = 0 ; i < stream_cnt ; + + i ) {
char * pkts_buf = SCCalloc ( 1 , 32 ) ;
if ( unlikely ( pkts_buf = = NULL ) ) {
SCLogError ( SC_ERR_MEM_ALLOC , " Failed to allocate memory for NAPATECH stream counter. " ) ;
SCLogError ( SC_ERR_MEM_ALLOC ,
" Failed to allocate memory for NAPATECH stream counter. " ) ;
exit ( EXIT_FAILURE ) ;
}
@ -258,7 +236,8 @@ static void *NapatechStatsLoop(void *arg)
char * byte_buf = SCCalloc ( 1 , 32 ) ;
if ( unlikely ( byte_buf = = NULL ) ) {
SCLogError ( SC_ERR_MEM_ALLOC , " Failed to allocate memory for NAPATECH stream counter. " ) ;
SCLogError ( SC_ERR_MEM_ALLOC ,
" Failed to allocate memory for NAPATECH stream counter. " ) ;
exit ( EXIT_FAILURE ) ;
}
snprintf ( byte_buf , 32 , " nt%d.bytes " , stream_config [ i ] . stream_id ) ;
@ -266,7 +245,8 @@ static void *NapatechStatsLoop(void *arg)
char * drop_buf = SCCalloc ( 1 , 32 ) ;
if ( unlikely ( drop_buf = = NULL ) ) {
SCLogError ( SC_ERR_MEM_ALLOC , " Failed to allocate memory for NAPATECH stream counter. " ) ;
SCLogError ( SC_ERR_MEM_ALLOC ,
" Failed to allocate memory for NAPATECH stream counter. " ) ;
exit ( EXIT_FAILURE ) ;
}
snprintf ( drop_buf , 32 , " nt%d.drop " , stream_config [ i ] . stream_id ) ;
@ -284,7 +264,7 @@ static void *NapatechStatsLoop(void *arg)
uint32_t num_active = UpdateStreamStats ( tv , hInfo , hStatStream ,
stream_cnt , stream_config , streamCounters ) ;
if ( num_active < stream_cnt ) {
if ( ! NapatechIsAutoConfigEnabled ( ) & & ( num_active < stream_cnt ) ) {
SCLogInfo ( " num_active: %d, stream_cnt: %d " , num_active , stream_cnt ) ;
SCLogWarning ( SC_ERR_NAPATECH_CONFIG_STREAM ,
" Some or all of the configured streams are not created. Proceeding with active streams. " ) ;
@ -333,7 +313,7 @@ static void *NapatechStatsLoop(void *arg)
# define HB_HIGHWATER 2048 //1982
static bool RegisteredStream ( uint16_t stream_id , uint16_t num_registered ,
NapatechStreamConfig registered_streams [ ] )
NapatechStreamConfig registered_streams [ ] )
{
for ( uint16_t reg_id = 0 ; reg_id < num_registered ; + + reg_id ) {
if ( stream_id = = registered_streams [ reg_id ] . stream_id ) {
@ -343,7 +323,76 @@ static bool RegisteredStream(uint16_t stream_id, uint16_t num_registered,
return false ;
}
uint16_t NapatechGetStreamConfig ( NapatechStreamConfig stream_config [ ] )
static uint32_t CountWorkerThreads ( void )
{
int worker_count = 0 ;
ConfNode * affinity ;
ConfNode * root = ConfGetNode ( " threading.cpu-affinity " ) ;
if ( root ! = NULL ) {
TAILQ_FOREACH ( affinity , & root - > head , next )
{
if ( strcmp ( affinity - > val , " decode-cpu-set " ) = = 0 | |
strcmp ( affinity - > val , " stream-cpu-set " ) = = 0 | |
strcmp ( affinity - > val , " reject-cpu-set " ) = = 0 | |
strcmp ( affinity - > val , " output-cpu-set " ) = = 0 ) {
continue ;
}
if ( strcmp ( affinity - > val , " worker-cpu-set " ) = = 0 ) {
ConfNode * node = ConfNodeLookupChild ( affinity - > head . tqh_first , " cpu " ) ;
ConfNode * lnode ;
enum CONFIG_SPECIFIER cpu_spec = CONFIG_SPECIFIER_UNDEFINED ;
TAILQ_FOREACH ( lnode , & node - > head , next )
{
uint8_t start , end ;
if ( strncmp ( lnode - > val , " all " , 4 ) = = 0 ) {
/* check that the sting in the config file is correctly specified */
if ( cpu_spec ! = CONFIG_SPECIFIER_UNDEFINED ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Only one Napatech port specifier type allowed. " ) ;
exit ( EXIT_FAILURE ) ;
}
cpu_spec = CONFIG_SPECIFIER_RANGE ;
worker_count = UtilCpuGetNumProcessorsConfigured ( ) ;
} else if ( strchr ( lnode - > val , ' - ' ) ) {
/* check that the sting in the config file is correctly specified */
if ( cpu_spec ! = CONFIG_SPECIFIER_UNDEFINED ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Only one Napatech port specifier type allowed. " ) ;
exit ( EXIT_FAILURE ) ;
}
cpu_spec = CONFIG_SPECIFIER_RANGE ;
char copystr [ 16 ] ;
strlcpy ( copystr , lnode - > val , 16 ) ;
start = atoi ( copystr ) ;
end = atoi ( strchr ( copystr , ' - ' ) + 1 ) ;
worker_count = end - start + 1 ;
} else {
/* check that the sting in the config file is correctly specified */
if ( cpu_spec = = CONFIG_SPECIFIER_RANGE ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Napatech port range specifiers cannot be combined with individual stream specifiers. " ) ;
exit ( EXIT_FAILURE ) ;
}
cpu_spec = CONFIG_SPECIFIER_INDIVIDUAL ;
+ + worker_count ;
}
}
break ;
}
}
}
return worker_count ;
}
int NapatechGetStreamConfig ( NapatechStreamConfig stream_config [ ] )
{
int status ;
char error_buffer [ 80 ] ; // Error buffer
@ -352,8 +401,12 @@ uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
NtInfoStream_t info_stream ;
NtInfo_t info ;
uint16_t instance_cnt = 0 ;
int use_all_streams ;
int use_all_streams = 0 ;
int set_cpu_affinity = 0 ;
ConfNode * ntstreams ;
uint16_t stream_id = 0 ;
uint16_t start = 0 ;
uint16_t end = 0 ;
for ( uint16_t i = 0 ; i < MAX_STREAMS ; + + i ) {
stream_config [ i ] . stream_id = 0 ;
@ -362,32 +415,33 @@ uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
}
if ( ConfGetBool ( " napatech.use-all-streams " , & use_all_streams ) = = 0 ) {
SCLogError ( SC_ERR_RUNMODE , " Failed retrieving napatech.use-all-streams from Conf " ) ;
exit ( EXIT_FAILURE ) ;
/* default is "no" */
use_all_streams = 0 ;
}
if ( ( status = NT_InfoOpen ( & info_stream , " SuricataStreamInfo " ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , " NT_InfoOpen failed: %s " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED ,
" NT_InfoOpen failed: %s " , error_buffer ) ;
return - 1 ;
}
if ( ( status = NT_StatOpen ( & hStatStream , " StatsStream " ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_RUNMODE , " NT_StatOpen() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
return - 1 ;
}
if ( use_all_streams ) {
info . cmd = NT_INFO_CMD_READ_STREAM ;
if ( ( status = NT_InfoRead ( info_stream , & info ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , " NT_InfoRead failed: %s " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED ,
" NT_InfoRead failed: %s " , error_buffer ) ;
return - 1 ;
}
uint16_t stream_id = 0 ;
while ( instance_cnt < info . u . stream . data . count ) {
/*
@ -405,8 +459,9 @@ uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatRead() failed: %s \n " , error_buffer ) ;
return 0 ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatRead() failed: %s \n " , error_buffer ) ;
return - 1 ;
}
if ( hStat . u . usageData_v0 . data . numHostBufferUsed = = 0 ) {
@ -421,61 +476,89 @@ uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
}
} else {
/* When not using the default streams we need to parse the array of streams from the conf */
if ( ( ntstreams = ConfGetNode ( " napatech.streams " ) ) = = NULL ) {
SCLogError ( SC_ERR_RUNMODE , " Failed retrieving napatech.streams from Conf " ) ;
exit ( EXIT_FAILURE ) ;
}
ConfGetBool ( " threading.set-cpu-affinity " , & set_cpu_affinity ) ;
if ( NapatechIsAutoConfigEnabled ( ) & & ( set_cpu_affinity = = 1 ) ) {
start = 0 ;
end = CountWorkerThreads ( ) - 1 ;
} else {
/* When not using the default streams we need to
* parse the array of streams from the conf */
if ( ( ntstreams = ConfGetNode ( " napatech.streams " ) ) = = NULL ) {
SCLogError ( SC_ERR_RUNMODE ,
" Failed retrieving napatech.streams from Config " ) ;
if ( NapatechIsAutoConfigEnabled ( ) & & ( set_cpu_affinity = = 0 ) ) {
SCLogError ( SC_ERR_RUNMODE ,
" if set-cpu-affinity: no in conf then napatech.streams must be defined " ) ;
}
exit ( EXIT_FAILURE ) ;
}
/* Loop through all stream numbers in the array and register the devices */
ConfNode * stream ;
instance_cnt = 0 ;
/* Loop through all stream numbers in the array and register the devices */
ConfNode * stream ;
enum CONFIG_SPECIFIER stream_spec = CONFIG_SPECIFIER_UNDEFINED ;
instance_cnt = 0 ;
TAILQ_FOREACH ( stream , & ntstreams - > head , next ) {
uint16_t stream_id = 0 ;
TAILQ_FOREACH ( stream , & ntstreams - > head , next )
{
if ( stream = = NULL ) {
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , " Couldn't Parse Stream Configuration " ) ;
exit ( EXIT_FAILURE ) ;
}
if ( stream = = NULL ) {
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED ,
" Couldn't Parse Stream Configuration " ) ;
return - 1 ;
}
uint16_t start , end ;
if ( strchr ( stream - > val , ' - ' ) ) {
char copystr [ 16 ] ;
strlcpy ( copystr , stream - > val , 16 ) ;
if ( strchr ( stream - > val , ' - ' ) ) {
if ( stream_spec ! = CONFIG_SPECIFIER_UNDEFINED ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Only one Napatech stream range specifier allowed. " ) ;
return - 1 ;
}
stream_spec = CONFIG_SPECIFIER_RANGE ;
start = atoi ( copystr ) ;
end = atoi ( strchr ( copystr , ' - ' ) + 1 ) ;
} else {
stream_config [ instance_cnt ] . stream_id = atoi ( stream - > val ) ;
start = stream_config [ instance_cnt ] . stream_id ;
end = stream_config [ instance_cnt ] . stream_id ;
char copystr [ 16 ] ;
strlcpy ( copystr , stream - > val , 16 ) ;
start = atoi ( copystr ) ;
end = atoi ( strchr ( copystr , ' - ' ) + 1 ) ;
} else {
if ( stream_spec = = CONFIG_SPECIFIER_RANGE ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Napatech range and individual specifiers cannot be combined. " ) ;
exit ( EXIT_FAILURE ) ;
}
stream_spec = CONFIG_SPECIFIER_INDIVIDUAL ;
stream_config [ instance_cnt ] . stream_id = atoi ( stream - > val ) ;
start = stream_config [ instance_cnt ] . stream_id ;
end = stream_config [ instance_cnt ] . stream_id ;
}
}
SCLogInfo ( " %s start: %d end: %d " , stream - > val , start , end ) ;
}
for ( stream_id = start ; stream_id < = end ; + + stream_id ) {
/* if we get here it is configured in the .yaml file */
stream_config [ instance_cnt ] . stream_id = stream_id ;
for ( stream_id = start ; stream_id < = end ; + + stream_id ) {
/* if we get here it is configured in the .yaml file */
stream_config [ instance_cnt ] . stream_id = stream_id ;
/* Check to see if it is an active stream */
memset ( & hStat , 0 , sizeof ( NtStatistics_t ) ) ;
/* Check to see if it is an active stream */
memset ( & hStat , 0 , sizeof ( NtStatistics_t ) ) ;
/* Read usage data for the chosen stream ID */
hStat . cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0 ;
hStat . u . usageData_v0 . streamid = ( uint8_t ) stream_config [ instance_cnt ] . stream_id ;
/* Read usage data for the chosen stream ID */
hStat . cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0 ;
hStat . u . usageData_v0 . streamid =
( uint8_t ) stream_config [ instance_cnt ] . stream_id ;
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatRead() failed: %s \n " , error_buffer ) ;
return 0 ;
}
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatRead() failed: %s \n " , error_buffer ) ;
return - 1 ;
}
if ( hStat . u . usageData_v0 . data . numHostBufferUsed > 0 ) {
stream_config [ instance_cnt ] . is_active = true ;
}
instance_cnt + + ;
if ( hStat . u . usageData_v0 . data . numHostBufferUsed > 0 ) {
stream_config [ instance_cnt ] . is_active = true ;
}
instance_cnt + + ;
}
}
@ -484,20 +567,19 @@ uint16_t NapatechGetStreamConfig(NapatechStreamConfig stream_config[])
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_RUNMODE , " NT_StatClose() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
return - 1 ;
}
if ( ( status = NT_InfoClose ( info_stream ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED ,
" NT_InfoClose failed: %s " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
" NT_InfoClose failed: %s " , error_buffer ) ;
return - 1 ;
}
return instance_cnt ;
}
static void * NapatechBufMonitorLoop ( void * arg )
{
ThreadVars * tv = ( ThreadVars * ) arg ;
@ -523,27 +605,33 @@ static void *NapatechBufMonitorLoop(void *arg)
/* Open the info and Statistics */
if ( ( status = NT_InfoOpen ( & hInfo , " InfoStream " ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoOpen() failed: %s \n " , error_buffer ) ;
exit ( 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_InfoOpen() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
if ( ( status = NT_StatOpen ( & hStatStream , " StatsStream " ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatOpen() failed: %s \n " , error_buffer ) ;
exit ( 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatOpen() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
/* Read the info on all streams instantiated in the system */
hStreamInfo . cmd = NT_INFO_CMD_READ_STREAM ;
if ( ( status = NT_InfoRead ( hInfo , & hStreamInfo ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoRead() failed: %s \n " , error_buffer ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_InfoRead() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
NapatechStreamConfig registered_streams [ MAX_STREAMS ] ;
uint16_t num_registered = NapatechGetStreamConfig ( registered_streams ) ;
int num_registered = NapatechGetStreamConfig ( registered_streams ) ;
if ( num_registered = = - 1 ) {
exit ( EXIT_FAILURE ) ;
}
TmThreadsSetFlag ( tv , THV_INIT_DONE ) ;
while ( 1 ) {
@ -558,7 +646,8 @@ static void *NapatechBufMonitorLoop(void *arg)
hStreamInfo . cmd = NT_INFO_CMD_READ_STREAM ;
if ( ( status = NT_InfoRead ( hInfo , & hStreamInfo ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoRead() failed: %s \n " , error_buffer ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_InfoRead() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
@ -580,8 +669,9 @@ static void *NapatechBufMonitorLoop(void *arg)
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatRead() failed: %s \n " , error_buffer ) ;
exit ( 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED ,
" NT_StatRead() failed: %s \n " , error_buffer ) ;
exit ( EXIT_FAILURE ) ;
}
if ( hStat . u . usageData_v0 . data . numHostBufferUsed = = 0 ) {
@ -594,7 +684,9 @@ static void *NapatechBufMonitorLoop(void *arg)
ave_OB_fill_level [ stream_id ] = 0 ;
ave_HB_fill_level [ stream_id ] = 0 ;
for ( uint32_t hb_count = 0 ; hb_count < hStat . u . usageData_v0 . data . numHostBufferUsed ; hb_count + + ) {
for ( uint32_t hb_count = 0 ;
hb_count < hStat . u . usageData_v0 . data . numHostBufferUsed ;
hb_count + + ) {
OB_fill_level [ hb_count ] =
( ( 100 * hStat . u . usageData_v0 . data . hb [ hb_count ] . onboardBuffering . used ) /
@ -623,11 +715,13 @@ static void *NapatechBufMonitorLoop(void *arg)
/* Host Buffer Fill Level warnings... */
if ( ave_HB_fill_level [ stream_id ] > = ( HB_alert_level [ stream_id ] + alertInterval ) ) {
while ( ave_HB_fill_level [ stream_id ] > = HB_alert_level [ stream_id ] + alertInterval ) {
while ( ave_HB_fill_level [ stream_id ] > = HB_alert_level [ stream_id ]
+ alertInterval ) {
HB_alert_level [ stream_id ] + = alertInterval ;
}
SCLogInfo ( " nt%d - Increasing Host Buffer Fill Level : %4d%% " ,
stream_id , ave_HB_fill_level [ stream_id ] ) ;
stream_id , ave_HB_fill_level [ stream_id ] - 1 ) ;
}
if ( HB_alert_level [ stream_id ] > 0 ) {
@ -673,7 +767,7 @@ static void *NapatechBufMonitorLoop(void *arg)
if ( ( status = NT_InfoClose ( hInfo ) ) ! = NT_SUCCESS ) {
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) - 1 ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_InfoClose() failed: %s \n " , error_buffer ) ;
exit ( 1 ) ;
exit ( EXIT_FAILURE ) ;
}
/* Close the statistics stream */
@ -681,7 +775,7 @@ static void *NapatechBufMonitorLoop(void *arg)
/* Get the status code as text */
NT_ExplainError ( status , error_buffer , sizeof ( error_buffer ) ) ;
SCLogError ( SC_ERR_NAPATECH_INIT_FAILED , " NT_StatClose() failed: %s \n " , error_buffer ) ;
exit ( 1 ) ;
exit ( EXIT_FAILURE ) ;
}
SCLogDebug ( " Exiting NapatechStatsLoop " ) ;
@ -733,4 +827,253 @@ void NapatechStartStats(void)
return ;
}
bool NapatechSetupNuma ( uint32_t stream , uint32_t numa )
{
uint32_t status = 0 ;
static NtConfigStream_t hconfig ;
char ntpl_cmd [ 64 ] ;
snprintf ( ntpl_cmd , 64 , " setup[numanode=%d] = streamid == %d " , numa , stream ) ;
NtNtplInfo_t ntpl_info ;
if ( ( status = NT_ConfigOpen ( & hconfig , " ConfigStream " ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , status ) ;
return false ;
}
if ( ( status = NT_NTPL ( hconfig , ntpl_cmd , & ntpl_info , NT_NTPL_PARSER_VALIDATE_NORMAL ) ) = = NT_SUCCESS ) {
status = ntpl_info . ntplId ;
} else {
NAPATECH_NTPL_ERROR ( ntpl_cmd , ntpl_info , status ) ;
return false ;
}
return status ;
}
static bool NapatechSetHashmode ( uint32_t * filter_id )
{
uint32_t status = 0 ;
const char * hash_mode ;
static NtConfigStream_t hconfig ;
char ntpl_cmd [ 64 ] ;
NtNtplInfo_t ntpl_info ;
* filter_id = 0 ;
/* Get the hashmode from the conf file. */
ConfGetValue ( " napatech.hashmode " , & hash_mode ) ;
snprintf ( ntpl_cmd , 64 , " hashmode = %s " , hash_mode ) ;
/* Issue the NTPL command */
if ( ( status = NT_ConfigOpen ( & hconfig , " ConfigStream " ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , status ) ;
return false ;
}
if ( ( status = NT_NTPL ( hconfig , ntpl_cmd , & ntpl_info ,
NT_NTPL_PARSER_VALIDATE_NORMAL ) ) = = NT_SUCCESS ) {
* filter_id = ntpl_info . ntplId ;
SCLogInfo ( " Napatech hashmode: %s ID: %d " , hash_mode , status ) ;
} else {
NAPATECH_NTPL_ERROR ( ntpl_cmd , ntpl_info , status ) ;
status = 0 ;
}
return status ;
}
static uint32_t GetStreamNUMAs ( uint32_t stream_id , int stream_numas [ ] )
{
NtStatistics_t hStat ; // Stat handle.
NtStatStream_t hStatStream ;
int status ; // Status variable
for ( int i = 0 ; i < MAX_HOSTBUFFERS ; + + i )
stream_numas [ i ] = - 1 ;
if ( ( status = NT_StatOpen ( & hStatStream , " StatsStream " ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_INIT_FAILED , status ) ;
exit ( EXIT_FAILURE ) ;
}
char pktCntStr [ 4096 ] ;
memset ( pktCntStr , 0 , sizeof ( pktCntStr ) ) ;
/* Read usage data for the chosen stream ID */
hStat . cmd = NT_STATISTICS_READ_CMD_USAGE_DATA_V0 ;
hStat . u . usageData_v0 . streamid = ( uint8_t ) stream_id ;
if ( ( status = NT_StatRead ( hStatStream , & hStat ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_INIT_FAILED , status ) ;
exit ( EXIT_FAILURE ) ;
}
for ( uint32_t hb_id = 0 ; hb_id < hStat . u . usageData_v0 . data . numHostBufferUsed ; + + hb_id ) {
stream_numas [ hb_id ] = hStat . u . usageData_v0 . data . hb [ hb_id ] . numaNode ;
}
return hStat . u . usageData_v0 . data . numHostBufferUsed ;
}
uint32_t NapatechSetupTraffic ( uint32_t first_stream , uint32_t last_stream ,
uint32_t * filter_id , uint32_t * hash_id )
{
# define PORTS_SPEC_SIZE 64
char ports_spec [ PORTS_SPEC_SIZE ] ;
ConfNode * ntports ;
bool first_iteration = true ;
int status = 0 ;
static NtConfigStream_t hconfig ;
char ntpl_cmd [ 128 ] ;
NapatechSetHashmode ( hash_id ) ;
/* When not using the default streams we need to parse
* the array of streams from the conf
*/
if ( ( ntports = ConfGetNode ( " napatech.ports " ) ) = = NULL ) {
SCLogError ( SC_ERR_RUNMODE , " Failed retrieving napatech.ports from Conf " ) ;
exit ( EXIT_FAILURE ) ;
}
/* Loop through all ports in the array */
ConfNode * port ;
enum CONFIG_SPECIFIER stream_spec = CONFIG_SPECIFIER_UNDEFINED ;
/* Build the NTPL command using values in the config file. */
TAILQ_FOREACH ( port , & ntports - > head , next )
{
if ( port = = NULL ) {
SCLogError ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED ,
" Couldn't Parse Port Configuration " ) ;
exit ( EXIT_FAILURE ) ;
}
uint8_t start , end ;
if ( strncmp ( port - > val , " all " , 3 ) = = 0 ) {
/* check that the sting in the config file is correctly specified */
if ( stream_spec ! = CONFIG_SPECIFIER_UNDEFINED ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Only one Napatech port specifier type allowed. " ) ;
exit ( EXIT_FAILURE ) ;
}
stream_spec = CONFIG_SPECIFIER_RANGE ;
snprintf ( ports_spec , sizeof ( ports_spec ) , " all " ) ;
} else if ( strchr ( port - > val , ' - ' ) ) {
/* check that the sting in the config file is correctly specified */
if ( stream_spec ! = CONFIG_SPECIFIER_UNDEFINED ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Only one Napatech port specifier type allowed. " ) ;
exit ( EXIT_FAILURE ) ;
}
stream_spec = CONFIG_SPECIFIER_RANGE ;
char copystr [ 16 ] ;
strlcpy ( copystr , port - > val , sizeof ( copystr ) ) ;
start = atoi ( copystr ) ;
end = atoi ( strchr ( copystr , ' - ' ) + 1 ) ;
snprintf ( ports_spec , sizeof ( ports_spec ) , " port == (%d..%d) " , start , end ) ;
} else {
/* check that the sting in the config file is correctly specified */
if ( stream_spec = = CONFIG_SPECIFIER_RANGE ) {
SCLogError ( SC_ERR_NAPATECH_PARSE_CONFIG ,
" Napatech port range specifiers cannot be combined with individual stream specifiers. " ) ;
exit ( EXIT_FAILURE ) ;
}
stream_spec = CONFIG_SPECIFIER_INDIVIDUAL ;
/* Determine the ports to use on the NTPL assign statement*/
if ( first_iteration ) {
snprintf ( ports_spec , sizeof ( ports_spec ) , " port==%s " , port - > val ) ;
first_iteration = false ;
} else {
char temp [ PORTS_SPEC_SIZE ] ;
snprintf ( temp , sizeof ( temp ) , " %s,%s " , ports_spec , port - > val ) ;
snprintf ( ports_spec , sizeof ( ports_spec ) , " %s " , temp ) ;
}
}
}
/* Build the NTPL command */
snprintf ( ntpl_cmd , sizeof ( ntpl_cmd ) , " assign[streamid=(%d..%d)] = %s " ,
first_stream , last_stream , ports_spec ) ;
NtNtplInfo_t ntpl_info ;
if ( ( status = NT_ConfigOpen ( & hconfig , " ConfigStream " ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_INIT_FAILED , status ) ;
exit ( EXIT_FAILURE ) ;
}
if ( ( status = NT_NTPL ( hconfig , ntpl_cmd , & ntpl_info ,
NT_NTPL_PARSER_VALIDATE_NORMAL ) ) = = NT_SUCCESS ) {
* filter_id = ntpl_info . ntplId ;
status = ntpl_info . u . errorData . errCode ;
SCLogInfo ( " NTPL filter assignment \" %s \" returned filter id %4d " ,
ntpl_cmd , * filter_id ) ;
} else {
NAPATECH_NTPL_ERROR ( ntpl_cmd , ntpl_info , status ) ;
status = ntpl_info . u . errorData . errCode ;
return false ;
}
SCLogInfo ( " Host-buffer NUMA assignments: " ) ;
int numa_nodes [ MAX_HOSTBUFFERS ] ;
uint32_t stream_id ;
for ( stream_id = first_stream ; stream_id < last_stream ; + + stream_id ) {
char temp1 [ 256 ] ;
char temp2 [ 256 ] ;
uint32_t num_host_buffers = GetStreamNUMAs ( stream_id , numa_nodes ) ;
snprintf ( temp1 , 256 , " stream %d: " , stream_id ) ;
for ( uint32_t hb_id = 0 ; hb_id < num_host_buffers ; + + hb_id ) {
snprintf ( temp2 , 256 , " %s %d " , temp1 , numa_nodes [ hb_id ] ) ;
snprintf ( temp1 , 256 , " %s " , temp2 ) ;
}
SCLogInfo ( " %s " , temp1 ) ;
}
return status ;
}
bool NapatechDeleteFilter ( uint32_t filter_id )
{
uint32_t status = 0 ;
static NtConfigStream_t hconfig ;
char ntpl_cmd [ 64 ] ;
NtNtplInfo_t ntpl_info ;
/* issue an NTPL command to delete the filter */
snprintf ( ntpl_cmd , 64 , " delete = %d " , filter_id ) ;
if ( ( status = NT_ConfigOpen ( & hconfig , " ConfigStream " ) ) ! = NT_SUCCESS ) {
NAPATECH_ERROR ( SC_ERR_NAPATECH_STREAMS_REGISTER_FAILED , status ) ;
exit ( EXIT_FAILURE ) ;
}
if ( ( status = NT_NTPL ( hconfig , ntpl_cmd , & ntpl_info ,
NT_NTPL_PARSER_VALIDATE_NORMAL ) ) = = NT_SUCCESS ) {
status = ntpl_info . ntplId ;
SCLogInfo ( " Removed Napatech filter %d. " , filter_id ) ;
} else {
NAPATECH_NTPL_ERROR ( ntpl_cmd , ntpl_info , status ) ;
status = 0 ;
}
return status ;
}
# endif // HAVE_NAPATECH