1 1.1 rmind /*- 2 1.1 rmind * Copyright (c) 2013 The NetBSD Foundation, Inc. 3 1.1 rmind * All rights reserved. 4 1.1 rmind * 5 1.1 rmind * This code is derived from software contributed to The NetBSD Foundation 6 1.1 rmind * by Mindaugas Rasiukevicius. 7 1.1 rmind * 8 1.1 rmind * Redistribution and use in source and binary forms, with or without 9 1.1 rmind * modification, are permitted provided that the following conditions 10 1.1 rmind * are met: 11 1.1 rmind * 1. Redistributions of source code must retain the above copyright 12 1.1 rmind * notice, this list of conditions and the following disclaimer. 13 1.1 rmind * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 rmind * notice, this list of conditions and the following disclaimer in the 15 1.1 rmind * documentation and/or other materials provided with the distribution. 16 1.1 rmind * 17 1.1 rmind * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 rmind * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 rmind * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 rmind * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 rmind * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 rmind * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 rmind * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 rmind * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 rmind * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 rmind * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 rmind * POSSIBILITY OF SUCH DAMAGE. 28 1.1 rmind */ 29 1.1 rmind 30 1.1 rmind /* 31 1.10 rmind * NPF tests of BPF coprocessor. 32 1.1 rmind */ 33 1.1 rmind 34 1.8 christos #ifdef _KERNEL 35 1.1 rmind #include <sys/types.h> 36 1.1 rmind #include <sys/endian.h> 37 1.8 christos #endif 38 1.1 rmind 39 1.1 rmind #define NPF_BPFCOP 40 1.1 rmind #include "npf_impl.h" 41 1.1 rmind #include "npf_test.h" 42 1.1 rmind 43 1.3 rmind static bool lverbose = false; 44 1.3 rmind 45 1.1 rmind static int 46 1.3 rmind test_bpf_code(void *code, size_t size) 47 1.1 rmind { 48 1.6 rmind uint32_t memstore[BPF_MEMWORDS]; 49 1.4 rmind bpf_args_t bc_args; 50 1.11 rmind npf_cache_t *npc; 51 1.1 rmind struct mbuf *m; 52 1.3 rmind int ret, jret; 53 1.3 rmind void *jcode; 54 1.1 rmind 55 1.1 rmind /* Layer 3 (IP + TCP). */ 56 1.11 rmind m = mbuf_get_pkt(AF_INET, IPPROTO_TCP, 57 1.11 rmind "192.168.2.100", "10.0.0.1", 15000, 80); 58 1.12 joe npc = get_cached_pkt(m, NULL, NPF_RULE_LAYER_3); 59 1.8 christos #ifdef _NPF_STANDALONE 60 1.11 rmind bc_args.pkt = (const uint8_t *)nbuf_dataptr(npc->npc_nbuf); 61 1.8 christos #else 62 1.5 alnsn bc_args.pkt = (const uint8_t *)m; 63 1.8 christos #endif 64 1.6 rmind bc_args.buflen = m_length(m); 65 1.6 rmind bc_args.wirelen = bc_args.buflen; 66 1.6 rmind bc_args.mem = memstore; 67 1.11 rmind bc_args.arg = npc; 68 1.4 rmind 69 1.4 rmind ret = npf_bpf_filter(&bc_args, code, NULL); 70 1.3 rmind 71 1.3 rmind /* JIT-compiled code. */ 72 1.3 rmind jcode = npf_bpf_compile(code, size); 73 1.3 rmind if (jcode) { 74 1.4 rmind jret = npf_bpf_filter(&bc_args, NULL, jcode); 75 1.9 rmind assert(ret == jret); (void)jret; 76 1.3 rmind bpf_jit_freecode(jcode); 77 1.3 rmind } else if (lverbose) { 78 1.3 rmind printf("JIT-compilation failed\n"); 79 1.3 rmind } 80 1.11 rmind put_cached_pkt(npc); 81 1.1 rmind return ret; 82 1.1 rmind } 83 1.1 rmind 84 1.1 rmind static uint32_t 85 1.11 rmind npf_bpfcop_run(unsigned reg) 86 1.1 rmind { 87 1.1 rmind struct bpf_insn insns_npf_bpfcop[] = { 88 1.1 rmind BPF_STMT(BPF_MISC+BPF_COP, NPF_COP_L3), 89 1.1 rmind BPF_STMT(BPF_LD+BPF_W+BPF_MEM, reg), 90 1.1 rmind BPF_STMT(BPF_RET+BPF_A, 0), 91 1.1 rmind }; 92 1.3 rmind return test_bpf_code(&insns_npf_bpfcop, sizeof(insns_npf_bpfcop)); 93 1.1 rmind } 94 1.1 rmind 95 1.1 rmind static bool 96 1.1 rmind npf_bpfcop_test(void) 97 1.1 rmind { 98 1.1 rmind /* A <- IP version (4 or 6) */ 99 1.1 rmind struct bpf_insn insns_ipver[] = { 100 1.1 rmind BPF_STMT(BPF_MISC+BPF_COP, NPF_COP_L3), 101 1.1 rmind BPF_STMT(BPF_RET+BPF_A, 0), 102 1.1 rmind }; 103 1.11 rmind CHECK_TRUE(test_bpf_code(&insns_ipver, sizeof(insns_ipver)) == IPVERSION); 104 1.1 rmind 105 1.1 rmind /* BPF_MW_IPVERI <- IP version */ 106 1.11 rmind CHECK_TRUE(npf_bpfcop_run(BPF_MW_IPVER) == IPVERSION); 107 1.1 rmind 108 1.1 rmind /* BPF_MW_L4OFF <- L4 header offset */ 109 1.11 rmind CHECK_TRUE(npf_bpfcop_run(BPF_MW_L4OFF) == sizeof(struct ip)); 110 1.1 rmind 111 1.1 rmind /* BPF_MW_L4PROTO <- L4 protocol */ 112 1.11 rmind CHECK_TRUE(npf_bpfcop_run(BPF_MW_L4PROTO) == IPPROTO_TCP); 113 1.1 rmind 114 1.11 rmind return true; 115 1.1 rmind } 116 1.1 rmind 117 1.1 rmind bool 118 1.1 rmind npf_bpf_test(bool verbose) 119 1.1 rmind { 120 1.3 rmind lverbose = verbose; 121 1.11 rmind return npf_bpfcop_test(); 122 1.1 rmind } 123