bpf_trace_filter: plugin for BPF Trace Filtering

Change-Id: I342de0a375b783725aa2b621c1c70bc8bf646450
Signed-off-by: Mohammed Hawari <mohammed@hawari.fr>
Type: improvement
This commit is contained in:
Mohammed Hawari
2023-06-09 16:50:56 +02:00
committed by Beno�t Ganne
parent 52fa5f21b9
commit ccd3070958
15 changed files with 405 additions and 0 deletions

View File

@ -806,6 +806,11 @@ I: prom
M: Florin Coras <fcoras@cisco.com>
F: src/plugins/prom
Plugin - BPF Trace Filter
I: bpf_trace_filter
M: Mohammed Hawari <mohammed@hawari.fr>
F: src/plugins/bpf_trace_filter
cJSON
I: cjson
M: Ole Troan <ot@cisco.com>

View File

@ -79,6 +79,7 @@ DEB_DEPENDS += libelf-dev libpcap-dev # for libxdp (af_xdp)
DEB_DEPENDS += iperf3 # for 'make test TEST=vcl'
DEB_DEPENDS += nasm
DEB_DEPENDS += iperf ethtool # for 'make test TEST=vm_vpp_interfaces'
DEB_DEPENDS += libpcap-dev
LIBFFI=libffi6 # works on all but 20.04 and debian-testing

View File

@ -0,0 +1 @@
../../../src/plugins/bpf_trace_filter/bpf_trace_filter.rst

View File

@ -41,3 +41,4 @@ For more on plugins please refer to :ref:`add_plugin`.
acl_lookup_context
bufmon_doc
ip_session_redirect_doc
bpf_trace_filter

View File

@ -102,6 +102,7 @@ bms
Bn
boolean
bootup
bpf
Brockners
bsid
bss

View File

@ -0,0 +1,45 @@
# Copyright (c) 2023 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
vpp_find_path(PCAP_INCLUDE_DIR NAMES pcap.h)
if (NOT PCAP_INCLUDE_DIR)
message(WARNING "libpcap headers not found - bpf_trace_filter plugin disabled")
return()
endif()
vpp_plugin_find_library(bpf_trace_filter PCAP_LIB libpcap.so)
if (NOT PCAP_LIB)
message(WARNING "bpf_trace_filter plugin - missing libraries - bpf_trace_filter plugin disabled")
return()
endif()
set(CMAKE_REQUIRED_FLAGS "-fPIC")
set(CMAKE_REQUIRED_INCLUDES "${PCAP_INCLUDE_DIR}")
set(CMAKE_REQUIRED_LIBRARIES "${PCAP_LIB}")
include_directories(${PCAP_INCLUDE_DIR})
add_vpp_plugin(bpf_trace_filter
SOURCES
cli.c
plugin.c
bpf_trace_filter.c
api.c
API_FILES
bpf_trace_filter.api
LINK_LIBRARIES
${PCAP_LIB}
)

View File

@ -0,0 +1,8 @@
---
name: BPF Trace Filter
maintainer: Mohammed Hawari <mohammed@hawari.fr>
features:
- BPF Trace Filtering
description: "BPF Trace Filtering"
state: experimental
properties: [CLI, API]

View File

@ -0,0 +1,74 @@
/*
*------------------------------------------------------------------
* Copyright (c) 2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#include <vlib/vlib.h>
#include <bpf_trace_filter/bpf_trace_filter.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
/* define message IDs */
#include <bpf_trace_filter/bpf_trace_filter.api_enum.h>
#include <bpf_trace_filter/bpf_trace_filter.api_types.h>
#define REPLY_MSG_ID_BASE (bm->msg_id_base)
#include <vlibapi/api_helper_macros.h>
static void
vl_api_bpf_trace_filter_set_t_handler (vl_api_bpf_trace_filter_set_t *mp)
{
bpf_trace_filter_main_t *bm = &bpf_trace_filter_main;
vl_api_bpf_trace_filter_set_reply_t *rmp;
clib_error_t *err = 0;
int rv = 0;
u8 is_del;
char *bpf_expr;
is_del = !mp->is_add;
bpf_expr = vl_api_from_api_to_new_c_string (&mp->filter);
err = bpf_trace_filter_set_unset (bpf_expr, is_del);
if (err)
{
rv = -1;
clib_error_report (err);
}
vec_free (bpf_expr);
REPLY_MACRO (VL_API_BPF_TRACE_FILTER_SET_REPLY);
}
#include <bpf_trace_filter/bpf_trace_filter.api.c>
static clib_error_t *
bpf_trace_filter_plugin_api_hookup (vlib_main_t *vm)
{
bpf_trace_filter_main_t *bm = &bpf_trace_filter_main;
/* ask for a correctly-sized block of API message decode slots */
bm->msg_id_base = setup_message_id_table ();
return 0;
}
VLIB_API_INIT_FUNCTION (bpf_trace_filter_plugin_api_hookup);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,26 @@
/*
* bpf_trace_filter.api - BPF Trace filter API
*
* Copyright (c) 2023 Cisco and/or its affiliates
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
option version = "0.1.0";
autoreply define bpf_trace_filter_set
{
u32 client_index;
u32 context;
bool is_add [default = true];
string filter[];
};

View File

@ -0,0 +1,96 @@
/*
*------------------------------------------------------------------
* Copyright (c) 2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#include <vlib/vlib.h>
#include <bpf_trace_filter/bpf_trace_filter.h>
clib_error_t *
bpf_trace_filter_init (vlib_main_t *vm)
{
bpf_trace_filter_main_t *btm = &bpf_trace_filter_main;
btm->pcap = pcap_open_dead (DLT_EN10MB, 65535);
return 0;
}
int vnet_is_packet_traced (vlib_buffer_t *b, u32 classify_table_index,
int func);
clib_error_t *
bpf_trace_filter_set_unset (const char *bpf_expr, u8 is_del)
{
bpf_trace_filter_main_t *btm = &bpf_trace_filter_main;
if (is_del)
{
if (btm->prog_set)
{
btm->prog_set = 0;
pcap_freecode (&btm->prog);
}
}
else if (bpf_expr)
{
if (btm->prog_set)
pcap_freecode (&btm->prog);
btm->prog_set = 0;
if (pcap_compile (btm->pcap, &btm->prog, (char *) bpf_expr, 0,
PCAP_NETMASK_UNKNOWN))
{
return clib_error_return (0, "Failed pcap_compile of %s", bpf_expr);
}
btm->prog_set = 1;
}
return 0;
};
int
bpf_is_packed_traced (vlib_buffer_t *b, u32 classify_table_index, int func)
{
bpf_trace_filter_main_t *bfm = &bpf_trace_filter_main;
struct pcap_pkthdr phdr = { 0 };
int res;
int res1;
res1 = vnet_is_packet_traced (b, classify_table_index, 0);
if (res1 != 1)
return res1;
if (!bfm->prog_set)
return 1;
phdr.caplen = b->current_length;
phdr.len = b->current_length;
res = pcap_offline_filter (&bfm->prog, &phdr, vlib_buffer_get_current (b));
return res != 0;
}
VLIB_REGISTER_TRACE_FILTER_FUNCTION (bpf_trace_filter_fn, static) = {
.name = "bpf_trace_filter",
.description = "bpf based trace filter",
.priority = 10,
.function = bpf_is_packed_traced
};
VLIB_INIT_FUNCTION (bpf_trace_filter_init);
bpf_trace_filter_main_t bpf_trace_filter_main;
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,40 @@
/*
*------------------------------------------------------------------
* Copyright (c) 2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#ifndef _BPF_TRACE_FILTER_H_
#define _BPF_TRACE_FILTER_H_
#include <vlib/vlib.h>
#include <pcap.h>
typedef struct
{
pcap_t *pcap;
u16 msg_id_base;
u8 prog_set;
struct bpf_program prog;
} bpf_trace_filter_main_t;
extern bpf_trace_filter_main_t bpf_trace_filter_main;
clib_error_t *bpf_trace_filter_set_unset (const char *bpf_expr, u8 is_del);
#endif /* _BPF_TRACE_FILTER_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,4 @@
BPF Trace Filter Function
============================
This plugin provides a trace filter function that relies on a BPF interpreter to select which packets
must be traced.

View File

@ -0,0 +1,68 @@
/*
*------------------------------------------------------------------
* Copyright (c) 2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#include <stdint.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <inttypes.h>
#include <vlib/vlib.h>
#include <bpf_trace_filter/bpf_trace_filter.h>
#include <pcap.h>
static clib_error_t *
set_bpf_trace_filter_command_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
u8 *bpf_expr = 0;
u8 is_del = 0;
clib_error_t *err = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "del"))
is_del = 1;
else if (unformat (line_input, "%s", &bpf_expr))
;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
}
err = bpf_trace_filter_set_unset ((char *) bpf_expr, is_del);
unformat_free (line_input);
return err;
}
VLIB_CLI_COMMAND (set_bpf_trace_filter, static) = {
.path = "set bpf trace filter",
.short_help = "set bpf trace filter {<pcap string>}",
.function = set_bpf_trace_filter_command_fn,
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,33 @@
/*
*------------------------------------------------------------------
* Copyright (c) 2023 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#include <vlib/vlib.h>
#include <vnet/plugin/plugin.h>
#include <vpp/app/version.h>
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "BPF Trace Filter Plugin",
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -29,6 +29,8 @@
* @param u32 classify_table_index - classifier table index
* @return 0 => no trace, 1 => trace, -1 => error
*/
int vnet_is_packet_traced (vlib_buffer_t *b, u32 classify_table_index,
int func);
static inline int
vnet_is_packet_traced_inline (vlib_buffer_t * b,