Skip to content

Commit 80ae5ef

Browse files
authored
Merge pull request #1362 from sancppp/add_tc_ut
eBPF unit test: add general tc ut
2 parents 415508d + 8bcb39d commit 80ae5ef

File tree

7 files changed

+380
-3
lines changed

7 files changed

+380
-3
lines changed

bpf/kmesh/general/tc_mark_encrypt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ int tc_mark_encrypt(struct __sk_buff *ctx)
2222
if (!nodeinfo) {
2323
return TC_ACT_OK;
2424
}
25-
// 0x00d0 mean need encryption in ipsec
25+
// 0x00e0 mean need encryption in ipsec
2626
ctx->mark = 0x00e0;
2727
return TC_ACT_OK;
2828
}

test/bpf_ut/Makefile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ CLANG_FLAGS += -MD
2626

2727
.PHONY: all clean run
2828

29-
all: xdp_shutdown_in_userspace_test.o xdp_authz_offload_test.o workload_sockops_test.o
29+
all: xdp_shutdown_in_userspace_test.o \
30+
xdp_authz_offload_test.o \
31+
workload_sockops_test.o \
32+
tc_mark_encrypt_test.o \
33+
tc_mark_decrypt_test.o
34+
3035

3136
XDP_FLAGS = -I$(ROOT_DIR)/bpf/kmesh/ -I$(ROOT_DIR)/bpf/kmesh/workload/include -I$(ROOT_DIR)/api/v2-c
3237
xdp_%.o: xdp_%.c
@@ -36,6 +41,12 @@ WORKLOAD_SOCKOPS_FLAGS = -I$(ROOT_DIR)/bpf/kmesh/ -I$(ROOT_DIR)/bpf/kmesh/probes
3641
workload_sockops_test.o: workload_sockops_test.c
3742
$(QUIET) $(CLANG) $(CLANG_FLAGS) $(WORKLOAD_SOCKOPS_FLAGS) -c $< -o $@
3843

44+
TC_FLAGS = -I$(ROOT_DIR)/bpf/kmesh/ -I$(ROOT_DIR)/bpf/kmesh/general/include -I$(ROOT_DIR)/bpf/kmesh/general -I$(ROOT_DIR)/api/v2-c
45+
tc_mark_encrypt_test.o: tc_mark_encrypt_test.c
46+
$(QUIET) $(CLANG) $(CLANG_FLAGS) $(TC_FLAGS) -c $< -o $@
47+
tc_mark_decrypt_test.o: tc_mark_decrypt_test.c
48+
$(QUIET) $(CLANG) $(CLANG_FLAGS) $(TC_FLAGS) -c $< -o $@
49+
3950
clean:
4051
$(QUIET) rm -f $(wildcard *.o)
4152
$(QUIET) rm -f $(wildcard *.d)

test/bpf_ut/bpftest/bpf_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ func TestBPF(t *testing.T) {
103103
}
104104

105105
t.Run("Workload", testWorkload)
106+
t.Run("GeneralTC", testGeneralTC)
106107
}
107108

108109
// common functions
@@ -284,7 +285,7 @@ const (
284285
)
285286

286287
func subTest(t *testing.T, progSet programSet, resultMap *ebpf.Map) {
287-
// create ctx with the max allowed size(4k - head room - tailroom)
288+
// create data payload with the max allowed size(4k - head room - tailroom)
288289
data := make([]byte, 4096-256-320)
289290

290291
// ctx is only used for tc programs
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//go:build linux && (amd64 || arm64) && !aix && !ppc64
2+
3+
/*
4+
* Copyright The Kmesh Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at:
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package bpftests
20+
21+
import (
22+
"testing"
23+
24+
"github.com/cilium/ebpf"
25+
26+
"kmesh.net/kmesh/pkg/bpf/factory"
27+
"kmesh.net/kmesh/pkg/constants"
28+
)
29+
30+
func testGeneralTC(t *testing.T) {
31+
TCtests := []unitTests_BPF_PROG_TEST_RUN{
32+
{
33+
objFilename: "tc_mark_encrypt_test.o",
34+
uts: []unitTest_BPF_PROG_TEST_RUN{
35+
{
36+
name: "tc_mark_encrypt",
37+
setupInUserSpace: func(t *testing.T, coll *ebpf.Collection) {
38+
setBpfConfig(t, coll, &factory.GlobalBpfConfig{
39+
BpfLogLevel: constants.BPF_LOG_DEBUG,
40+
})
41+
},
42+
},
43+
},
44+
},
45+
{
46+
objFilename: "tc_mark_decrypt_test.o",
47+
uts: []unitTest_BPF_PROG_TEST_RUN{
48+
{
49+
name: "tc_mark_decrypt",
50+
setupInUserSpace: func(t *testing.T, coll *ebpf.Collection) {
51+
setBpfConfig(t, coll, &factory.GlobalBpfConfig{
52+
BpfLogLevel: constants.BPF_LOG_DEBUG,
53+
})
54+
},
55+
},
56+
},
57+
},
58+
}
59+
60+
for _, tt := range TCtests {
61+
t.Run(tt.objFilename, tt.run())
62+
}
63+
}

test/bpf_ut/include/tc_common.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
2+
/* Copyright Authors of Kmesh */
3+
4+
#pragma once
5+
6+
#define build_tc_packet(ctx, p_ethhdr, p_iphdr, p_tcphdr, body, body_len) \
7+
({ \
8+
int __ret = TEST_PASS; \
9+
\
10+
void *data = (void *)(long)((ctx)->data); \
11+
void *data_end = (void *)(long)((ctx)->data_end); \
12+
\
13+
/* Set Ethernet header */ \
14+
if (data + sizeof(struct ethhdr) > data_end) \
15+
return TEST_ERROR; \
16+
if (p_ethhdr) { \
17+
bpf_memcpy(data, (p_ethhdr), sizeof(struct ethhdr)); \
18+
} else { \
19+
/* Default Ethernet header */ \
20+
__maybe_unused const struct ethhdr default_eth = { \
21+
.h_source = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, \
22+
.h_dest = {0x12, 0x23, 0x34, 0x45, 0x56, 0x67}, \
23+
.h_proto = bpf_htons(ETH_P_IP)}; \
24+
bpf_memcpy(data, &default_eth, sizeof(struct ethhdr)); \
25+
} \
26+
data += sizeof(struct ethhdr); \
27+
\
28+
/* Set IP header */ \
29+
if (data + sizeof(struct iphdr) > data_end) \
30+
return TEST_ERROR; \
31+
if (p_iphdr) { \
32+
bpf_memcpy(data, (p_iphdr), sizeof(struct iphdr)); \
33+
} else { \
34+
/* Default IP header */ \
35+
__maybe_unused const unsigned int ip_payload_size = sizeof(struct tcphdr) + (body ? body_len : 0); \
36+
__maybe_unused const struct iphdr default_ip = { \
37+
.version = 4, \
38+
.ihl = 5, \
39+
.tot_len = bpf_htons(sizeof(struct iphdr) + ip_payload_size), \
40+
.id = 0x5438, \
41+
.frag_off = bpf_htons(IP_DF), \
42+
.ttl = 64, \
43+
.protocol = IPPROTO_TCP, \
44+
.saddr = 0x0F00000A, /* 10.0.0.15 */ \
45+
.daddr = 0x0100000A /* 10.0.0.1 - assuming DEST_IP */ \
46+
}; \
47+
bpf_memcpy(data, &default_ip, sizeof(struct iphdr)); \
48+
} \
49+
data += sizeof(struct iphdr); \
50+
\
51+
/* Set TCP header */ \
52+
if (data + sizeof(struct tcphdr) > data_end) \
53+
return TEST_ERROR; \
54+
if (p_tcphdr) { \
55+
bpf_memcpy(data, (p_tcphdr), sizeof(struct tcphdr)); \
56+
} else { \
57+
/* Default TCP header */ \
58+
__maybe_unused const struct tcphdr default_tcp = { \
59+
.source = bpf_htons(23445), \
60+
.dest = bpf_htons(80), /* assuming DEST_PORT */ \
61+
.seq = 2922048129, \
62+
.doff = 5, /* 5 * 4 = 20 bytes, no options */ \
63+
.syn = 1, \
64+
.window = 64240}; \
65+
bpf_memcpy(data, &default_tcp, sizeof(struct tcphdr)); \
66+
} \
67+
data += sizeof(struct tcphdr); \
68+
\
69+
/* Set payload data */ \
70+
if (body && body_len > 0) { \
71+
if (data + body_len > data_end) \
72+
return TEST_ERROR; \
73+
bpf_memcpy(data, body, body_len); \
74+
data += body_len; \
75+
} \
76+
/* Shrink data payload to the exact size we used */ \
77+
bpf_skb_change_tail(ctx, data - (void *)(long)((ctx)->data), 0); \
78+
__ret; \
79+
})
80+
81+
#define check_tc_packet(ctx, exp_status_code, exp_ethhdr, exp_iphdr, exp_tcphdr, exp_body, exp_body_len) \
82+
do { \
83+
void *data = (void *)(long)((ctx)->data); \
84+
void *data_end = (void *)(long)((ctx)->data_end); \
85+
\
86+
if (data + sizeof(__u32) > data_end) \
87+
test_fatal("status code out of bounds"); \
88+
if (exp_status_code) { \
89+
__u32 *status_code = (__u32 *)data; \
90+
if (*status_code != *(exp_status_code)) \
91+
test_fatal("status code mismatch, expected %u, got %u", *(exp_status_code), *status_code); \
92+
} \
93+
data += sizeof(__u32); \
94+
\
95+
if (data + sizeof(struct ethhdr) > data_end) \
96+
test_fatal("ethhdr out of bounds"); \
97+
if (exp_ethhdr) { \
98+
struct ethhdr *eth = (struct ethhdr *)data; \
99+
if (memcmp(eth, (exp_ethhdr), sizeof(struct ethhdr)) != 0) \
100+
test_fatal("ethhdr mismatch"); \
101+
} \
102+
data += sizeof(struct ethhdr); \
103+
\
104+
if (data + sizeof(struct iphdr) > data_end) \
105+
test_fatal("iphdr out of bounds"); \
106+
if (exp_iphdr) { \
107+
struct iphdr *ip = (struct iphdr *)data; \
108+
if (memcmp(ip, (exp_iphdr), sizeof(struct iphdr)) != 0) \
109+
test_fatal("iphdr mismatch"); \
110+
} \
111+
data += sizeof(struct iphdr); \
112+
\
113+
if (data + sizeof(struct tcphdr) > data_end) \
114+
test_fatal("tcphdr out of bounds"); \
115+
if (exp_tcphdr) { \
116+
struct tcphdr *tcp = (struct tcphdr *)data; \
117+
if (memcmp(tcp, (exp_tcphdr), sizeof(struct tcphdr)) != 0) \
118+
test_fatal("tcphdr mismatch"); \
119+
} \
120+
data += sizeof(struct tcphdr); \
121+
if (data + exp_body_len > data_end) \
122+
test_fatal("body out of bounds"); \
123+
if (exp_body) { \
124+
char *body = (char *)data; \
125+
if (memcmp(body, (exp_body), exp_body_len) != 0) \
126+
test_fatal("body mismatch"); \
127+
} \
128+
} while (0)

0 commit comments

Comments
 (0)