Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add netkit test for pkt_type

Add a test case to assert that the skb->pkt_type which was set from the BPF
program is retained from the netkit xmit side to the peer's device at tcx
ingress location.

# ./vmtest.sh -- ./test_progs -t netkit
[...]
./test_progs -t netkit
[ 1.140780] bpf_testmod: loading out-of-tree module taints kernel.
[ 1.141127] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel
[ 1.284601] tsc: Refined TSC clocksource calibration: 3408.006 MHz
[ 1.286672] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fd9b189d, max_idle_ns: 440795225691 ns
[ 1.290384] clocksource: Switched to clocksource tsc
#345 tc_netkit_basic:OK
#346 tc_netkit_device:OK
#347 tc_netkit_multi_links:OK
#348 tc_netkit_multi_opts:OK
#349 tc_netkit_neigh_links:OK
#350 tc_netkit_pkt_type:OK
Summary: 6/0 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20240524163619.26001-4-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
95348e46 998ffeb2

+118 -1
+84
tools/testing/selftests/bpf/prog_tests/tc_netkit.c
··· 99 99 return err; 100 100 } 101 101 102 + static void move_netkit(void) 103 + { 104 + ASSERT_OK(system("ip link set " netkit_peer " netns foo"), 105 + "move peer"); 106 + ASSERT_OK(system("ip netns exec foo ip link set dev " 107 + netkit_peer " up"), "up peer"); 108 + ASSERT_OK(system("ip netns exec foo ip addr add dev " 109 + netkit_peer " 10.0.0.2/24"), "addr peer"); 110 + } 111 + 102 112 static void destroy_netkit(void) 103 113 { 104 114 ASSERT_OK(system("ip link del dev " netkit_name), "del primary"); ··· 704 694 { 705 695 serial_test_tc_netkit_neigh_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY); 706 696 serial_test_tc_netkit_neigh_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY); 697 + } 698 + 699 + static void serial_test_tc_netkit_pkt_type_mode(int mode) 700 + { 701 + LIBBPF_OPTS(bpf_netkit_opts, optl_nk); 702 + LIBBPF_OPTS(bpf_tcx_opts, optl_tcx); 703 + int err, ifindex, ifindex2; 704 + struct test_tc_link *skel; 705 + struct bpf_link *link; 706 + 707 + err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS, 708 + &ifindex, true); 709 + if (err) 710 + return; 711 + 712 + ifindex2 = if_nametoindex(netkit_peer); 713 + ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2"); 714 + 715 + skel = test_tc_link__open(); 716 + if (!ASSERT_OK_PTR(skel, "skel_open")) 717 + goto cleanup; 718 + 719 + ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1, 720 + BPF_NETKIT_PRIMARY), 0, "tc1_attach_type"); 721 + ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc7, 722 + BPF_TCX_INGRESS), 0, "tc7_attach_type"); 723 + 724 + err = test_tc_link__load(skel); 725 + if (!ASSERT_OK(err, "skel_load")) 726 + goto cleanup; 727 + 728 + assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0); 729 + assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0); 730 + 731 + link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl_nk); 732 + if (!ASSERT_OK_PTR(link, "link_attach")) 733 + goto cleanup; 734 + 735 + skel->links.tc1 = link; 736 + 737 + assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1); 738 + assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0); 739 + 740 + link = bpf_program__attach_tcx(skel->progs.tc7, ifindex2, &optl_tcx); 741 + if (!ASSERT_OK_PTR(link, "link_attach")) 742 + goto cleanup; 743 + 744 + skel->links.tc7 = link; 745 + 746 + assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1); 747 + assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 1); 748 + 749 + move_netkit(); 750 + 751 + tc_skel_reset_all_seen(skel); 752 + skel->bss->set_type = true; 753 + ASSERT_EQ(send_icmp(), 0, "icmp_pkt"); 754 + 755 + ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); 756 + ASSERT_EQ(skel->bss->seen_tc7, true, "seen_tc7"); 757 + 758 + ASSERT_EQ(skel->bss->seen_host, true, "seen_host"); 759 + ASSERT_EQ(skel->bss->seen_mcast, true, "seen_mcast"); 760 + cleanup: 761 + test_tc_link__destroy(skel); 762 + 763 + assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0); 764 + destroy_netkit(); 765 + } 766 + 767 + void serial_test_tc_netkit_pkt_type(void) 768 + { 769 + serial_test_tc_netkit_pkt_type_mode(NETKIT_L2); 770 + serial_test_tc_netkit_pkt_type_mode(NETKIT_L3); 707 771 }
+34 -1
tools/testing/selftests/bpf/progs/test_tc_link.c
··· 4 4 5 5 #include <linux/bpf.h> 6 6 #include <linux/if_ether.h> 7 - 7 + #include <linux/stddef.h> 8 + #include <linux/if_packet.h> 8 9 #include <bpf/bpf_endian.h> 9 10 #include <bpf/bpf_helpers.h> 10 11 ··· 17 16 bool seen_tc4; 18 17 bool seen_tc5; 19 18 bool seen_tc6; 19 + bool seen_tc7; 20 + 21 + bool set_type; 22 + 20 23 bool seen_eth; 24 + bool seen_host; 25 + bool seen_mcast; 21 26 22 27 SEC("tc/ingress") 23 28 int tc1(struct __sk_buff *skb) ··· 35 28 if (bpf_skb_load_bytes(skb, 0, &eth, sizeof(eth))) 36 29 goto out; 37 30 seen_eth = eth.h_proto == bpf_htons(ETH_P_IP); 31 + seen_host = skb->pkt_type == PACKET_HOST; 32 + if (seen_host && set_type) { 33 + eth.h_dest[0] = 4; 34 + if (bpf_skb_store_bytes(skb, 0, &eth, sizeof(eth), 0)) 35 + goto fail; 36 + bpf_skb_change_type(skb, PACKET_MULTICAST); 37 + } 38 38 out: 39 39 seen_tc1 = true; 40 + fail: 40 41 return TCX_NEXT; 41 42 } 42 43 ··· 80 65 int tc6(struct __sk_buff *skb) 81 66 { 82 67 seen_tc6 = true; 68 + return TCX_PASS; 69 + } 70 + 71 + SEC("tc/ingress") 72 + int tc7(struct __sk_buff *skb) 73 + { 74 + struct ethhdr eth = {}; 75 + 76 + if (skb->protocol != __bpf_constant_htons(ETH_P_IP)) 77 + goto out; 78 + if (bpf_skb_load_bytes(skb, 0, &eth, sizeof(eth))) 79 + goto out; 80 + if (eth.h_dest[0] == 4 && set_type) { 81 + seen_mcast = skb->pkt_type == PACKET_MULTICAST; 82 + bpf_skb_change_type(skb, PACKET_HOST); 83 + } 84 + out: 85 + seen_tc7 = true; 83 86 return TCX_PASS; 84 87 }