diff --git a/userspace/libsinsp/event.h b/userspace/libsinsp/event.h index 90d7446e24..ed1540e168 100644 --- a/userspace/libsinsp/event.h +++ b/userspace/libsinsp/event.h @@ -45,7 +45,7 @@ typedef struct filtercheck_field_info { ppm_param_type m_type; ///< Field type. filtercheck_field_flags m_flags; ///< Field flags. - ppm_print_format m_print_format; ///< If this is a numeric field, this flag specifies if it should be rendered as decimal or hex. + ppm_print_format m_print_format; ///< If this is a numeric field, this flag specifies if it should be rendered as decimal or hex. char m_name[64]; ///< Field name. char m_description[1024]; ///< Field description. }filtercheck_field_info; @@ -78,7 +78,7 @@ class SINSP_PUBLIC sinsp_evt_param inline void init(char* valptr, uint16_t len) { m_val = valptr; - m_len = len; + m_len = len; } friend class sinsp_evt; @@ -86,9 +86,9 @@ class SINSP_PUBLIC sinsp_evt_param /*! \brief Event class. - This class is returned by \ref sinsp::next() and encapsulates the state - related to a captured event, and includes a bunch of members to manipulate - events and their parameters, including parsing, formatting and extracting + This class is returned by \ref sinsp::next() and encapsulates the state + related to a captured event, and includes a bunch of members to manipulate + events and their parameters, including parsing, formatting and extracting state like the event process or FD. */ class SINSP_PUBLIC sinsp_evt @@ -160,8 +160,8 @@ class SINSP_PUBLIC sinsp_evt } /*! - \brief Get the event type. - + \brief Get the event type. + \note For a list of event types, refer to \ref etypes. */ inline uint16_t get_type() @@ -227,14 +227,14 @@ class SINSP_PUBLIC sinsp_evt /*! \brief Return the information about the FD on which this event operated. - \note For events that are not I/O related, get_fd_info() returns NULL. + \note For events that are not I/O related, get_fd_info() returns NULL. */ sinsp_fdinfo_t* get_fd_info(); /*! \brief Return the number of the FD associated with this event. - \note For events that are not I/O related, get_fd_num() returns sinsp_evt::INVALID_FD_NUM. + \note For events that are not I/O related, get_fd_num() returns sinsp_evt::INVALID_FD_NUM. */ int64_t get_fd_num(); @@ -255,7 +255,7 @@ class SINSP_PUBLIC sinsp_evt \param id The parameter number. - \note Refer to the g_event_info structure in driver/event_table.c for + \note Refer to the g_event_info structure in driver/event_table.c for a list of event descriptions. */ const struct ppm_param_info* get_param_info(uint32_t id); @@ -278,7 +278,7 @@ class SINSP_PUBLIC sinsp_evt \brief Get a parameter as a C++ string. \param name The parameter name. - \param resolved If true, the library will try to resolve the parameter + \param resolved If true, the library will try to resolve the parameter before returning it. For example, and FD number will be converted into the correspondent file, TCP tuple, etc. */ @@ -403,6 +403,7 @@ VISIBILITY_PRIVATE friend class sinsp_analyzer; friend class sinsp_filter_check_event; friend class sinsp_filter_check_thread; + friend class sinsp_evttype_filter; friend class sinsp_dumper; friend class sinsp_analyzer_fd_listener; friend class sinsp_analyzer_parsers; diff --git a/userspace/libsinsp/filter.cpp b/userspace/libsinsp/filter.cpp index 817168a29a..9daaee6e58 100644 --- a/userspace/libsinsp/filter.cpp +++ b/userspace/libsinsp/filter.cpp @@ -1917,4 +1917,84 @@ sinsp_filter* sinsp_filter_compiler::compile_() return m_filter; } +sinsp_evttype_filter::sinsp_evttype_filter() +{ + memset(m_filter_by_evttype, 0, PPM_EVENT_MAX * sizeof(list *)); +} + +sinsp_evttype_filter::~sinsp_evttype_filter() +{ + for(int i = 0; i < PPM_EVENT_MAX; i++) + { + if(m_filter_by_evttype[i]) + { + delete m_filter_by_evttype[i]; + m_filter_by_evttype[i] = NULL; + } + } + + m_catchall_evttype_filters.clear(); + + for(auto filter : m_evttype_filters) + { + delete filter; + } + m_evttype_filters.clear(); +} + +void sinsp_evttype_filter::add(list &evttypes, + sinsp_filter *filter) +{ + m_evttype_filters.push_back(filter); + + if(evttypes.size() == 0) + { + m_catchall_evttype_filters.push_back(filter); + } + else + { + + for(auto evttype: evttypes) + { + list *filters = m_filter_by_evttype[evttype]; + if(filters == NULL) + { + filters = new list(); + m_filter_by_evttype[evttype] = filters; + } + + filters->push_back(filter); + } + } +} + +bool sinsp_evttype_filter::run(sinsp_evt *evt) +{ + // + // First run any catchall event type filters (ones that did not + // explicitly specify any event type. + // + for(sinsp_filter *filt : m_catchall_evttype_filters) + { + if(filt->run(evt) == true) + { + return true; + } + } + + list *filters = m_filter_by_evttype[evt->m_pevt->type]; + + if(filters) + { + for(sinsp_filter *filt : *filters) + { + if(filt->run(evt) == true) + { + return true; + } + } + } + + return false; +} #endif // HAS_FILTERING diff --git a/userspace/libsinsp/filter.h b/userspace/libsinsp/filter.h index ad76f4fef8..1028dd86d4 100644 --- a/userspace/libsinsp/filter.h +++ b/userspace/libsinsp/filter.h @@ -156,6 +156,40 @@ class SINSP_PUBLIC sinsp_filter_compiler friend class sinsp_evt_formatter; }; +/*! + \brief This class represents a filter optimized using event + types. It actually consists of collections of sinsp_filter objects + grouped by event type. +*/ + +class SINSP_PUBLIC sinsp_evttype_filter +{ +public: + sinsp_evttype_filter(); + virtual ~sinsp_evttype_filter(); + + void add(list &evttypes, + sinsp_filter* filter); + + bool run(sinsp_evt *evt); + +private: + + // Maps from event type to filter. There can be multiple + // filters per event type. + list *m_filter_by_evttype[PPM_EVENT_MAX]; + + // It's possible to add an event type filter with an empty + // list of event types, meaning it should run for all event + // types. + list m_catchall_evttype_filters; + + // This holds all the filters in + // m_filter_by_evttype/m_catchall_evttype_filters, so they can + // be cleaned up. + list m_evttype_filters; +}; + /*@}*/ #endif // HAS_FILTERING diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index b40f702782..9cdd8530a8 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -190,7 +190,7 @@ void sinsp_parser::process_event(sinsp_evt *evt) #if defined(HAS_FILTERING) && defined(HAS_CAPTURE_FILTERING) bool do_filter_later = false; - if(m_inspector->m_filter || m_inspector->m_evttype_filters.size() > 0) + if(m_inspector->m_filter || m_inspector->m_evttype_filter) { ppm_event_flags eflags = evt->get_info_flags(); diff --git a/userspace/libsinsp/sinsp.cpp b/userspace/libsinsp/sinsp.cpp index a9528d88d7..17dd9a1464 100644 --- a/userspace/libsinsp/sinsp.cpp +++ b/userspace/libsinsp/sinsp.cpp @@ -77,6 +77,7 @@ sinsp::sinsp() : #ifdef HAS_FILTERING m_filter = NULL; + m_evttype_filter = NULL; #endif m_fds_to_remove = new vector; @@ -143,8 +144,6 @@ sinsp::sinsp() : m_mesos_last_watch_time_ns = 0; m_filter_proc_table_when_saving = false; - - memset(m_filter_by_evttype, 0, PPM_EVENT_MAX * sizeof(list *)); } sinsp::~sinsp() @@ -552,22 +551,11 @@ void sinsp::close() m_filter = NULL; } - for(int i = 0; i < PPM_EVENT_MAX; i++) - { - if(m_filter_by_evttype[i]) - { - delete m_filter_by_evttype[i]; - m_filter_by_evttype[i] = NULL; - } - } - - m_catchall_evttype_filters.clear(); - - for(auto filter : m_evttype_filters) + if(m_evttype_filter != NULL) { - delete filter; + delete m_evttype_filter; + m_evttype_filter = NULL; } - m_evttype_filters.clear(); #endif } @@ -1373,27 +1361,13 @@ const string sinsp::get_filter() void sinsp::add_evttype_filter(list &evttypes, sinsp_filter *filter) { - m_evttype_filters.push_back(filter); - - if(evttypes.size() == 0) + // Create the evttype filter if it doesn't exist. + if(m_evttype_filter == NULL) { - m_catchall_evttype_filters.push_back(filter); + m_evttype_filter = new sinsp_evttype_filter(); } - else - { - - for(auto evttype: evttypes) - { - list *filters = m_filter_by_evttype[evttype]; - if(filters == NULL) - { - filters = new list(); - m_filter_by_evttype[evttype] = filters; - } - filters->push_back(filter); - } - } + m_evttype_filter->add(evttypes, filter); } bool sinsp::run_filters_on_evt(sinsp_evt *evt) @@ -1407,28 +1381,10 @@ bool sinsp::run_filters_on_evt(sinsp_evt *evt) } // - // Then run any catchall event type filters (ones that did not - // explicitly specify any event type. - // - for(sinsp_filter *filt : m_catchall_evttype_filters) - { - if(filt->run(evt) == true) - { - return true; - } - } - - list *filters = m_filter_by_evttype[evt->m_pevt->type]; - - if(filters) + // Then run the evttype filter, if there is one. + if(m_evttype_filter && m_evttype_filter->run(evt) == true) { - for(sinsp_filter *filt : *filters) - { - if(filt->run(evt) == true) - { - return true; - } - } + return true; } return false; diff --git a/userspace/libsinsp/sinsp.h b/userspace/libsinsp/sinsp.h index d4358519a8..00384638ba 100644 --- a/userspace/libsinsp/sinsp.h +++ b/userspace/libsinsp/sinsp.h @@ -853,21 +853,9 @@ VISIBILITY_PRIVATE #ifdef HAS_FILTERING uint64_t m_firstevent_ts; sinsp_filter* m_filter; + sinsp_evttype_filter *m_evttype_filter; string m_filterstring; - // Maps from event type to filter. There can be multiple - // filters per event type. - list *m_filter_by_evttype[PPM_EVENT_MAX]; - - // It's possible to add an event type filter with an empty - // list of event types, meaning it should run for all event - // types. - list m_catchall_evttype_filters; - - // This holds all the filters in - // m_filter_by_evttype/m_catchall_evttype_filters, so they can - // be cleaned up. - list m_evttype_filters; #endif //