[PATCH v2 6/6] test/bpf: check that bpf_convert can be JIT'd
Stephen Hemminger
stephen at networkplumber.org
Thu Jun 18 22:47:10 CEST 2026
Add followup in bpf conversion tests to make sure resulting
code was also run through JIT and that JIT produces
same results as non-JIT.
Reduce log output to make it easier to match which
expression might be causing issues.
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
app/test/test_bpf.c | 94 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 79 insertions(+), 15 deletions(-)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index 3a88434c3c..973dd7d659 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -8,6 +8,7 @@
#include <inttypes.h>
#include <unistd.h>
+#include <rte_byteorder.h>
#include <rte_memory.h>
#include <rte_debug.h>
#include <rte_hexdump.h>
@@ -32,6 +33,7 @@ test_bpf(void)
#include <rte_bpf.h>
#include <rte_ether.h>
#include <rte_ip.h>
+#include <rte_udp.h>
/* Tests of most simple BPF programs (no instructions, one instruction etc.) */
@@ -4529,6 +4531,7 @@ test_bpf_match(pcap_t *pcap, const char *str,
int ret = -1;
uint64_t rc;
+ printf("%s '%s'\n", __func__, str);
if (pcap_compile(pcap, &fcode, str, 1, PCAP_NETMASK_UNKNOWN)) {
printf("%s@%d: pcap_compile(\"%s\") failed: %s;\n",
__func__, __LINE__, str, pcap_geterr(pcap));
@@ -4550,6 +4553,24 @@ test_bpf_match(pcap_t *pcap, const char *str,
}
rc = rte_bpf_exec(bpf, mb);
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ {
+ struct rte_bpf_jit jit;
+
+ rte_bpf_get_jit(bpf, &jit);
+ if (jit.func == NULL) {
+ printf("%s@%d: no JIT generated\n", __func__, __LINE__);
+ goto error;
+ }
+
+ fflush(stdout);
+ uint64_t rc_jit = jit.func(mb);
+ if (rc_jit != rc) {
+ printf("%s@%d: JIT return code does not match\n", __func__, __LINE__);
+ goto error;
+ }
+ }
+#endif
/* The return code from bpf capture filter is non-zero if matched */
ret = (rc == 0);
error:
@@ -4560,23 +4581,16 @@ test_bpf_match(pcap_t *pcap, const char *str,
return ret;
}
-/* Basic sanity test can we match a IP packet */
-static int
-test_bpf_filter_sanity(pcap_t *pcap)
+/* Setup mbuf for filter test */
+static void
+dummy_ip_prep(void *data, uint16_t plen)
{
- const uint32_t plen = 100;
- struct rte_mbuf mb, *m;
- uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
struct {
struct rte_ether_hdr eth_hdr;
struct rte_ipv4_hdr ip_hdr;
- } *hdr;
+ struct rte_udp_hdr udp_hdr;
+ } *hdr = data;
- memset(&mb, 0, sizeof(mb));
- dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
- m = &mb;
-
- hdr = rte_pktmbuf_mtod(m, typeof(hdr));
hdr->eth_hdr = (struct rte_ether_hdr) {
.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4),
@@ -4589,13 +4603,32 @@ test_bpf_filter_sanity(pcap_t *pcap)
.src_addr = rte_cpu_to_be_32(RTE_IPV4_LOOPBACK),
.dst_addr = rte_cpu_to_be_32(RTE_IPV4_BROADCAST),
};
+ hdr->udp_hdr = (struct rte_udp_hdr) {
+ .src_port = rte_rand_max(UINT16_MAX),
+ .dst_port = rte_cpu_to_be_16(9), /* discard port */
+ .dgram_len = rte_cpu_to_be_16(plen - sizeof(struct rte_ipv4_hdr)),
+ .dgram_cksum = 0,
+ };
+}
+
+
+/* Basic sanity test can we match a IP packet */
+static int
+test_bpf_filter_sanity(pcap_t *pcap)
+{
+ struct rte_mbuf mb = { 0 };
+ uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
+ const uint32_t plen = 100;
+
+ dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
+ dummy_ip_prep(rte_pktmbuf_mtod(&mb, void *), plen);
- if (test_bpf_match(pcap, "ip", m) != 0) {
+ if (test_bpf_match(pcap, "ip", &mb) != 0) {
printf("%s@%d: filter \"ip\" doesn't match test data\n",
__func__, __LINE__);
return -1;
}
- if (test_bpf_match(pcap, "not ip", m) == 0) {
+ if (test_bpf_match(pcap, "not ip", &mb) == 0) {
printf("%s@%d: filter \"not ip\" does match test data\n",
__func__, __LINE__);
return -1;
@@ -4648,10 +4681,15 @@ static const char * const sample_filters[] = {
static int
test_bpf_filter(pcap_t *pcap, const char *s)
{
+ struct rte_mbuf mb = { 0 };
+ uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
+ const uint32_t plen = 100;
struct bpf_program fcode;
struct rte_bpf_prm *prm = NULL;
struct rte_bpf *bpf = NULL;
+ int ret = -1;
+ printf("%s '%s'\n", __func__, s);
if (pcap_compile(pcap, &fcode, s, 1, PCAP_NETMASK_UNKNOWN)) {
printf("%s@%d: pcap_compile('%s') failed: %s;\n",
__func__, __LINE__, s, pcap_geterr(pcap));
@@ -4665,8 +4703,10 @@ test_bpf_filter(pcap_t *pcap, const char *s)
goto error;
}
+#ifdef DEBUG
printf("bpf convert for \"%s\" produced:\n", s);
rte_bpf_dump(stdout, prm->ins, prm->nb_ins);
+#endif
bpf = rte_bpf_load(prm);
if (bpf == NULL) {
@@ -4675,6 +4715,30 @@ test_bpf_filter(pcap_t *pcap, const char *s)
goto error;
}
+ dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
+ dummy_ip_prep(rte_pktmbuf_mtod(&mb, void *), plen);
+
+ uint64_t rc = rte_bpf_exec(bpf, &mb);
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ {
+ struct rte_bpf_jit jit;
+
+ rte_bpf_get_jit(bpf, &jit);
+ if (jit.func == NULL) {
+ printf("%s@%d: no JIT generated\n", __func__, __LINE__);
+ goto error;
+ }
+
+ fflush(stdout);
+ uint64_t rc_jit = jit.func(&mb);
+ if (rc_jit != rc) {
+ printf("%s@%d: JIT return code does not match\n", __func__, __LINE__);
+ goto error;
+ }
+ }
+#endif
+ ret = 0;
+
error:
if (bpf)
rte_bpf_destroy(bpf);
@@ -4685,7 +4749,7 @@ test_bpf_filter(pcap_t *pcap, const char *s)
rte_free(prm);
pcap_freecode(&fcode);
- return (bpf == NULL) ? -1 : 0;
+ return ret;
}
static int
--
2.53.0
More information about the dev
mailing list