1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2017 Mellanox Technologies, Ltd 3 */ 4 5 #include <errno.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <sys/queue.h> 9 10 #include <rte_malloc.h> 11 #include <rte_eth_tap.h> 12 #include <tap_flow.h> 13 #include <tap_autoconf.h> 14 #include <tap_tcmsgs.h> 15 #include <tap_bpf.h> 16 #include <tap_bpf_insns.h> 17 18 /** 19 * Load BPF program (section cls_q) into the kernel and return a bpf fd 20 * 21 * @param queue_idx 22 * Queue index matching packet cb 23 * 24 * @return 25 * -1 if the BPF program couldn't be loaded. An fd (int) otherwise. 26 */ 27 int tap_flow_bpf_cls_q(__u32 queue_idx) 28 { 29 cls_q_insns[1].imm = queue_idx; 30 31 return bpf_load(BPF_PROG_TYPE_SCHED_CLS, 32 (struct bpf_insn *)cls_q_insns, 33 RTE_DIM(cls_q_insns), 34 "Dual BSD/GPL"); 35 } 36 37 /** 38 * Load BPF program (section l3_l4) into the kernel and return a bpf fd. 39 * 40 * @param[in] key_idx 41 * RSS MAP key index 42 * 43 * @param[in] map_fd 44 * BPF RSS map file descriptor 45 * 46 * @return 47 * -1 if the BPF program couldn't be loaded. An fd (int) otherwise. 48 */ 49 int tap_flow_bpf_calc_l3_l4_hash(__u32 key_idx, int map_fd) 50 { 51 l3_l4_hash_insns[4].imm = key_idx; 52 l3_l4_hash_insns[9].imm = map_fd; 53 54 return bpf_load(BPF_PROG_TYPE_SCHED_ACT, 55 (struct bpf_insn *)l3_l4_hash_insns, 56 RTE_DIM(l3_l4_hash_insns), 57 "Dual BSD/GPL"); 58 } 59 60 /** 61 * Helper function to convert a pointer to unsigned 64 bits 62 * 63 * @param[in] ptr 64 * pointer to address 65 * 66 * @return 67 * 64 bit unsigned long type of pointer address 68 */ 69 static inline __u64 ptr_to_u64(const void *ptr) 70 { 71 return (__u64)(unsigned long)ptr; 72 } 73 74 /** 75 * Call BPF system call 76 * 77 * @param[in] cmd 78 * BPF command for program loading, map creation, map entry update, etc 79 * 80 * @param[in] attr 81 * System call attributes relevant to system call command 82 * 83 * @param[in] size 84 * size of attr parameter 85 * 86 * @return 87 * -1 if BPF system call failed, 0 otherwise 88 */ 89 static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, 90 unsigned int size) 91 { 92 return syscall(__NR_bpf, cmd, attr, size); 93 } 94 95 /** 96 * Load BPF instructions to kernel 97 * 98 * @param[in] type 99 * BPF program type: classifier or action 100 * 101 * @param[in] insns 102 * Array of BPF instructions (equivalent to BPF instructions) 103 * 104 * @param[in] insns_cnt 105 * Number of BPF instructions (size of array) 106 * 107 * @param[in] license 108 * License string that must be acknowledged by the kernel 109 * 110 * @return 111 * -1 if the BPF program couldn't be loaded, fd (file descriptor) otherwise 112 */ 113 static int bpf_load(enum bpf_prog_type type, 114 const struct bpf_insn *insns, 115 size_t insns_cnt, 116 const char *license) 117 { 118 union bpf_attr attr = {}; 119 120 bzero(&attr, sizeof(attr)); 121 attr.prog_type = type; 122 attr.insn_cnt = (__u32)insns_cnt; 123 attr.insns = ptr_to_u64(insns); 124 attr.license = ptr_to_u64(license); 125 attr.log_buf = ptr_to_u64(NULL); 126 attr.log_level = 0; 127 attr.kern_version = 0; 128 129 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 130 } 131 132 /** 133 * Create BPF map for RSS rules 134 * 135 * @param[in] key_size 136 * map RSS key size 137 * 138 * @param[in] value_size 139 * Map RSS value size 140 * 141 * @param[in] max_entries 142 * Map max number of RSS entries (limit on max RSS rules) 143 * 144 * @return 145 * -1 if BPF map couldn't be created, map fd otherwise 146 */ 147 int tap_flow_bpf_rss_map_create(unsigned int key_size, 148 unsigned int value_size, 149 unsigned int max_entries) 150 { 151 union bpf_attr attr = {}; 152 153 bzero(&attr, sizeof(attr)); 154 attr.map_type = BPF_MAP_TYPE_HASH; 155 attr.key_size = key_size; 156 attr.value_size = value_size; 157 attr.max_entries = max_entries; 158 159 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); 160 } 161 162 /** 163 * Update RSS entry in BPF map 164 * 165 * @param[in] fd 166 * RSS map fd 167 * 168 * @param[in] key 169 * Pointer to RSS key whose entry is updated 170 * 171 * @param[in] value 172 * Pointer to RSS new updated value 173 * 174 * @return 175 * -1 if RSS entry failed to be updated, 0 otherwise 176 */ 177 int tap_flow_bpf_update_rss_elem(int fd, void *key, void *value) 178 { 179 union bpf_attr attr = {}; 180 181 bzero(&attr, sizeof(attr)); 182 183 attr.map_type = BPF_MAP_TYPE_HASH; 184 attr.map_fd = fd; 185 attr.key = ptr_to_u64(key); 186 attr.value = ptr_to_u64(value); 187 attr.flags = BPF_ANY; 188 189 return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); 190 } 191