summaryrefslogtreecommitdiff
path: root/infra/test/TestDataPathTrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'infra/test/TestDataPathTrace.c')
-rw-r--r--infra/test/TestDataPathTrace.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/infra/test/TestDataPathTrace.c b/infra/test/TestDataPathTrace.c
new file mode 100644
index 0000000..6d0ff34
--- /dev/null
+++ b/infra/test/TestDataPathTrace.c
@@ -0,0 +1,468 @@
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cmocka.h>
+
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+
+#include "dp_trace.h"
+#include "ldbc.h"
+#include "mrb_define.h"
+
+unsigned int g_logger_to_stdout = 1;
+unsigned int g_logger_level = LOG_DEBUG;
+struct dp_trace_process * trace;
+struct rte_mempool * mempool;
+
+/* 73 Ether/IPv4/UDP/G-VxLan/Ether/VLAN/IPv4/TCP
+
+ Outer Ether e8:4d:d0:ca:3a:1f -> 58:69:6c:6f:96:f3
+ Outer IPv4 1.1.15.100 -> 10.0.4.120
+ Outer UDP 60014 -> 4789
+
+ Outer Ether 64:f6:9d:5f:b9:76 -> a4:93:4c:c6:e5:5f
+ Inner IPv4 125.33.49.137 -> 39.66.162.89
+ Inner TCP 28402→11235
+*/
+
+/* Frame (114 bytes) */
+static const unsigned char pkt73[114] = {
+ 0xe8, 0x4d, 0xd0, 0xca, 0x3a, 0x1f, 0x58, 0x69, /* .M..:.Xi */
+ 0x6c, 0x6f, 0x96, 0xf3, 0x08, 0x00, 0x45, 0x00, /* lo....E. */
+ 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x11, /* .d...... */
+ 0x9e, 0xac, 0x01, 0x01, 0x0f, 0x64, 0x0a, 0x00, /* .....d.. */
+ 0x04, 0x78, 0xea, 0x6e, 0x12, 0xb5, 0x00, 0x50, /* .x.n...P */
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x50, /* .......P */
+ 0x01, 0x00, 0x64, 0xf6, 0x9d, 0x5f, 0xb9, 0x76, /* ..d.._.v */
+ 0xa4, 0x93, 0x4c, 0xc6, 0xe5, 0x5f, 0x81, 0x00, /* ..L.._.. */
+ 0x00, 0x01, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28, /* ....E..( */
+ 0x59, 0x6f, 0x40, 0x00, 0x7b, 0x06, 0x2e, 0x1b, /* Yo@.{... */
+ 0x7d, 0x21, 0x31, 0x89, 0x27, 0x42, 0xa2, 0x59, /* }!1.'B.Y */
+ 0x6e, 0xf2, 0x2b, 0xe3, 0xa5, 0x40, 0xd8, 0x7f, /* n.+..@.. */
+ 0x9d, 0x5c, 0x74, 0xba, 0x50, 0x10, 0xfb, 0xb8, /* .\t.P... */
+ 0x11, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* .)...... */
+ 0x00, 0x00 /* .. */
+};
+
+int contains_substring(const char * str, const char * substr, size_t len);
+
+static int setup_testcase(void ** state)
+{
+ const char * argv[] = {"TestDataPathTrace", "-c", "0x1", "--no-huge", "-m", "512", "--no-pci"};
+ if (rte_eal_init(RTE_DIM(argv), (char **)argv) < 0)
+ {
+ rte_exit(EXIT_FAILURE, "failed at rte_eal_init()");
+ return 1;
+ }
+ return 0;
+}
+
+static int teardown_testCase(void ** state)
+{
+ rte_eal_cleanup();
+ return 0;
+}
+
+static int setup(void ** state)
+{
+ // create trace
+ trace = dp_trace_process_create(DP_TRACE_PROCESS_MARSIO);
+ trace->inst->enable = true;
+ unsigned int sz_align_priv = RTE_ALIGN(sizeof(struct mrb_metadata), RTE_MBUF_PRIV_ALIGN);
+ mempool = rte_pktmbuf_pool_create("dp_trace_dump_pool", 16, 0, sz_align_priv,
+ DP_TRACE_RECORD_SIZE + RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ return 0;
+}
+
+void dp_trace_process_destroy(struct dp_trace_process * trace, enum dp_trace_process_type process_tpye)
+{
+ // This function is for unit testing only. This instance created by marsio or app should not be deleted
+ // manually. It accompanies the entire life cycle of the process.
+ if (process_tpye == DP_TRACE_PROCESS_MARSIO)
+ {
+ rte_mempool_free(trace->inst->pool);
+ rte_mempool_free(mempool);
+ for (unsigned int i = 0; i < trace->inst->nr_ring; i++)
+ {
+ rte_ring_free(trace->inst->ring[i]);
+ }
+ FREE(trace->inst);
+ FREE(trace);
+ }
+ else
+ {
+ FREE(trace);
+ }
+}
+
+static int teardown(void ** state)
+{
+ dp_trace_process_destroy(trace, DP_TRACE_PROCESS_MARSIO);
+ return 0;
+}
+
+struct rte_mbuf * mbuf_construct(const unsigned char * pkt, unsigned int len)
+{
+ if (trace == NULL)
+ return NULL;
+
+ struct rte_mbuf * pkt_mbuf = rte_pktmbuf_alloc(mempool);
+ unsigned int sz_align_priv = RTE_ALIGN(sizeof(struct mrb_metadata), RTE_MBUF_PRIV_ALIGN);
+
+ uint16_t data_off = sizeof(struct rte_mbuf) + sz_align_priv;
+ unsigned char * data_addr = (unsigned char *)pkt_mbuf->buf_addr + data_off;
+ memcpy(data_addr, pkt, len);
+ pkt_mbuf->data_off = data_off;
+ pkt_mbuf->data_len = len;
+ pkt_mbuf->pkt_len = len;
+ pkt_mbuf->nb_segs = 1;
+ pkt_mbuf->next = NULL;
+
+ // parse mbuf
+ struct pkt_parser _pkt_handler;
+ struct pkt_parser_result _pkt_result;
+ pkt_parser_init(&_pkt_handler, &_pkt_result, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX);
+ pkt_parser_exec(&_pkt_handler, pkt_mbuf);
+
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt_mbuf, 1);
+ struct pkt_parser_result * pkt_parser_result = &mrb_meta->pkt_parser_result;
+ memcpy(pkt_parser_result, &_pkt_result, sizeof(struct pkt_parser_result));
+ mrb_meta->dp_trace_buffer = NULL;
+
+ return pkt_mbuf;
+}
+
+static void testcase_packet_construct(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+
+ struct rte_mbuf * mbuf = (struct rte_mbuf *)rte_zmalloc(NULL, sizeof(struct rte_mbuf), 0);
+ mbuf->buf_len = sizeof(pkt73);
+ mbuf->buf_addr = (void *)(const char *)pkt73;
+ mbuf->data_off = 0;
+ mbuf->data_len = sizeof(pkt73);
+ mbuf->pkt_len = sizeof(pkt73);
+ mbuf->nb_segs = 1;
+ mbuf->next = NULL;
+
+ struct pkt_parser _pkt_handler;
+ struct pkt_parser_result _pkt_parser;
+ pkt_parser_init(&_pkt_handler, &_pkt_parser, LAYER_TYPE_ALL, MR_PKT_PARSER_LAYERS_MAX);
+ pkt_parser_exec(&_pkt_handler, mbuf);
+ unsigned int inner_ether_offset = _pkt_parser.layers[4].offset;
+
+ assert_true(mrb_meta->pkt_parser_result.layers[4].offset == inner_ether_offset);
+
+ FREE(mbuf);
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_instance_create(void ** state)
+{
+ assert_true(trace->inst != NULL);
+}
+
+static void testcase_job_init(void ** state)
+{
+ int n;
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ n = dp_trace_job_add(trace, &desc);
+ assert_true(n >= 0);
+ assert_true(trace->inst->job_ctx[0].used == true);
+}
+
+static void testcase_job_destroy(void ** state)
+{
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ struct dp_trace_job_desc desc_2 = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 1,
+ .bpf_expr = "vlan && ip src 125.33.49.137",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc_2);
+
+ dp_trace_jobs_destroy(trace, 1 | 1 << 1);
+
+ assert_true(trace->inst->job_ctx[0].used == false);
+ assert_true(trace->inst->job_ctx[1].used == false);
+}
+
+static void testcase_job_bpf_match(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+ unsigned int offset = mrb_meta->pkt_parser_result.layers[4].offset;
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ struct dp_trace_job_desc desc_2 = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 1,
+ .bpf_expr = "vlan && ip src 125.33.49.137",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc_2);
+
+ dp_trace_filter_exec(trace, pkt73_mbuf, offset, 0);
+ u_int16_t ret = dp_trace_job_id_bitmap_get(trace, pkt73_mbuf);
+ assert_true(ret == 3);
+
+ struct dp_trace_buffer * dp_trace_buffer = (struct dp_trace_buffer *)mrb_meta->dp_trace_buffer;
+ assert_true(dp_trace_buffer != NULL);
+ assert_true(dp_trace_buffer->jobs == 3);
+
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_job_bpf_match_external_and_internal(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ip src 1.1.15.100",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ struct dp_trace_job_desc desc_2 = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 1,
+ .bpf_expr = "vlan && ip src 125.33.49.137",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc_2);
+
+ dp_trace_filter_exec(trace, pkt73_mbuf, 0, 0);
+ u_int16_t ret = dp_trace_job_id_bitmap_get(trace, pkt73_mbuf);
+ assert_true(ret == 3);
+
+ struct dp_trace_buffer * dp_trace_buffer = (struct dp_trace_buffer *)mrb_meta->dp_trace_buffer;
+ assert_true(dp_trace_buffer != NULL);
+ assert_true(dp_trace_buffer->jobs == 3);
+
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_job_bpf_unmatch(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+ unsigned int offset = mrb_meta->pkt_parser_result.layers[4].offset;
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "vlan && ip src 127.0.0.1",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ dp_trace_filter_exec(trace, pkt73_mbuf, offset, 0);
+ u_int16_t ret = dp_trace_job_id_bitmap_get(trace, pkt73_mbuf);
+ assert_true(ret == 0);
+
+ assert_true(mrb_meta->dp_trace_buffer == NULL);
+
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_job_emit_trace(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 1,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ mrb_meta->packet_create_from_nf = 1;
+ memset(&mrb_meta->pkt_parser_result, 0, sizeof(mrb_meta->pkt_parser_result));
+
+ dp_trace_filter_exec(trace, pkt73_mbuf, 0, rte_lcore_id());
+
+ struct dp_trace_record_meta meta = {DP_TRACE_MEASUREMENT_TYPE_TRACE, "test", "emit", NULL};
+ dp_trace_record_emit_str(trace, pkt73_mbuf, rte_lcore_id(), &meta, "abc");
+
+ struct dp_trace_record_meta meta_2 = {DP_TRACE_MEASUREMENT_TYPE_TRACE, "test", "emit", NULL};
+ dp_trace_record_emit_str(trace, pkt73_mbuf, rte_lcore_id(), &meta_2, "def");
+
+ struct dp_trace_buffer * dp_trace_buffer = (struct dp_trace_buffer *)mrb_meta->dp_trace_buffer;
+
+ char * cur = dp_trace_buffer->buffer;
+ struct dp_trace_record_header * record_header = (struct dp_trace_record_header *)(cur);
+ char * str = cur + sizeof(struct dp_trace_record_header);
+ unsigned int str_len = record_header->recode_len;
+ assert_true(contains_substring(str, "abc", str_len) == 1);
+
+ cur += sizeof(struct dp_trace_record_header) + str_len;
+ record_header = (struct dp_trace_record_header *)(cur);
+ str = cur + sizeof(struct dp_trace_record_header);
+ assert_true(contains_substring(str, "def", str_len) == 1);
+
+ // Excessive content will not cause buffer overflow
+ char big_buf[DP_TRACE_RECORD_SIZE] = {};
+ memset(big_buf, 'a', DP_TRACE_RECORD_SIZE - 1);
+ dp_trace_record_emit_str(trace, pkt73_mbuf, rte_lcore_id(), &meta_2, big_buf);
+
+ assert_true(dp_trace_buffer->buffer_used <= DP_TRACE_RECORD_SIZE);
+
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_job_strip_to_ring(void ** state)
+{
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ struct mrb_metadata * mrb_meta = (struct mrb_metadata *)mrbuf_cz_data(pkt73_mbuf, 1);
+ unsigned int offset = mrb_meta->pkt_parser_result.layers[4].offset;
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 10,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ dp_trace_filter_exec(trace, pkt73_mbuf, offset, rte_lcore_id());
+
+ struct dp_trace_record_meta meta = {DP_TRACE_MEASUREMENT_TYPE_TRACE, "test", "emit", NULL};
+ dp_trace_record_emit_str(trace, pkt73_mbuf, rte_lcore_id(), &meta, "abc");
+
+ dp_trace_record_write(trace, pkt73_mbuf, rte_lcore_id());
+
+ unsigned int trace_record_cnt = 0;
+ for (unsigned int i = 0; i < trace->nr_ring; i++)
+ {
+ trace_record_cnt += rte_ring_count(trace->ring[i]);
+ }
+ assert_true(trace_record_cnt == 1);
+
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+}
+
+static void testcase_job_max_record_count(void ** state)
+{
+ unsigned int lcore_id = rte_lcore_id();
+
+ struct dp_trace_job_desc desc = {
+ .enable = true,
+ .measurement_type = DP_TRACE_MEASUREMENT_TYPE_TRACE,
+ .rule_index = 0,
+ .bpf_expr = "ether host 64:f6:9d:5f:b9:76",
+ .pkt_cnt_max = 2,
+ .sampling = 1,
+ };
+ dp_trace_job_add(trace, &desc);
+
+ struct rte_mbuf * pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ dp_trace_filter_exec(trace, pkt73_mbuf, 0, 0);
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+
+ assert_true(trace->statistics[lcore_id].record_buf_alloc_success == 1);
+
+ pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ dp_trace_filter_exec(trace, pkt73_mbuf, 0, 0);
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+
+ assert_true(trace->statistics[lcore_id].record_buf_alloc_success == 2);
+
+ pkt73_mbuf = mbuf_construct(pkt73, sizeof(pkt73));
+ dp_trace_filter_exec(trace, pkt73_mbuf, 0, 0);
+ infra_rte_pktmbuf_free(pkt73_mbuf);
+
+ assert_true(trace->statistics[lcore_id].record_buf_alloc_success == 2);
+}
+
+int main(int argc, char * argv[])
+{
+
+ const struct CMUnitTest testcase_trace[] = {
+ cmocka_unit_test_setup_teardown(testcase_packet_construct, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_instance_create, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_init, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_destroy, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_bpf_match, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_bpf_match_external_and_internal, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_bpf_unmatch, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_emit_trace, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_strip_to_ring, setup, teardown),
+ cmocka_unit_test_setup_teardown(testcase_job_max_record_count, setup, teardown),
+ };
+
+ // 0 on success, or the number of failed tests.
+ int ret = cmocka_run_group_tests(testcase_trace, setup_testcase, teardown_testCase);
+
+ // Pass the return value to ctest. Report an error if it is non-zero
+ return ret;
+}
+
+//////////////////////////////////// helper function ////////////////////////////////////
+
+int contains_substring(const char * str, const char * substr, size_t len)
+{
+ size_t substr_len = strlen(substr);
+ for (size_t i = 0; i <= len - substr_len; i++)
+ {
+ if (strncmp(&str[i], substr, substr_len) == 0)
+ {
+ return 1;
+ }
+ }
+ return -1;
+} \ No newline at end of file