History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says: ==================== bpf-next 2018-11-30 The following pull-request contains BPF updates for your *net-next* tree. (Getting out bit earlier this time to pull in a dependency from bpf.) The main changes are: 1) Add libbpf ABI versioning and document API naming conventions as well as ABI versioning process, from Andrey. 2) Add a new sk_msg_pop_data() helper for sk_msg based BPF programs that is used in conjunction with sk_msg_push_data() for adding / removing meta data to the msg data, from John. 3) Optimize convert_bpf_ld_abs() for 0 offset and fix various lib and testsuite build failures on 32 bit, from David. 4) Make BPF prog dump for !JIT identical to how we dump subprogs when JIT is in use, from Yonghong. 5) Rename btf_get_from_id() to make it more conform with libbpf API naming conventions, from Martin. 6) Add a missing BPF kselftest config item, from Naresh. ====================

David S. Miller committed 7 years ago

Commit 93029d72 parents 3d58c9c b42699525 files · +760 −115Browse files

Unified · Split

25 files
  1. include/linux/bpf.h +4 −2
  2. include/linux/bpf_verifier.h +0 −1
  3. include/uapi/linux/bpf.h +15 −1
  4. kernel/bpf/core.c +2 −1
  5. kernel/bpf/syscall.c +8 −25
  6. kernel/bpf/verifier.c +38 −17
  7. net/core/filter.c +173 −1
  8. net/ipv4/tcp_bpf.c +14 −3
  9. net/tls/tls_sw.c +9 −2
  10. tools/bpf/bpftool/map.c +2 −2
  11. tools/bpf/bpftool/prog.c +1 −1
  12. tools/include/uapi/linux/bpf.h +15 −1
  13. tools/lib/bpf/Makefile +21 −2
  14. tools/lib/bpf/README.rst +139 −0
  15. tools/lib/bpf/btf.c +2 −2
  16. tools/lib/bpf/btf.h +1 −1
  17. tools/lib/bpf/libbpf.c +2 −0
  18. tools/lib/bpf/libbpf.map +121 −0
  19. tools/lib/bpf/libbpf_errno.c +1 −0
  20. tools/testing/selftests/bpf/bpf_helpers.h +2 −0
  21. tools/testing/selftests/bpf/config +1 −0
  22. tools/testing/selftests/bpf/test_btf.c +4 −31
  23. tools/testing/selftests/bpf/test_progs.c +5 −5
  24. tools/testing/selftests/bpf/test_sockmap.c +123 −4
  25. tools/testing/selftests/bpf/test_sockmap_kern.h +57 −13
include/linux/bpf.h+4−2
@@ -299,7 +299,8 @@ struct bpf_prog_aux { · 298 unmodified lines
299 u32 max_pkt_offset;299 u32 max_pkt_offset;
300 u32 stack_depth;300 u32 stack_depth;
301 u32 id;301 u32 id;
302 u32 func_cnt;302 u32 func_cnt; /* used by non-func prog as the number of func progs */
303 u32 func_idx; /* 0 for non-func prog, the index in func array for func prog */
303 bool offload_requested;304 bool offload_requested;
304 struct bpf_prog **func;305 struct bpf_prog **func;
305 void *jit_data; /* JIT specific data. arch dependent */306 void *jit_data; /* JIT specific data. arch dependent */
@@ -317,7 +318,8 @@ struct bpf_prog_aux { · 11 unmodified lines
317#endif318#endif
318 struct bpf_prog_offload *offload;319 struct bpf_prog_offload *offload;
319 struct btf *btf;320 struct btf *btf;
320 u32 type_id; /* type id for this prog/func */321 struct bpf_func_info *func_info;
322 u32 func_info_cnt;
321 union {323 union {
322 struct work_struct work;324 struct work_struct work;
323 struct rcu_head rcu;325 struct rcu_head rcu;
include/linux/bpf_verifier.h+0−1
@@ -204,7 +204,6 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) · 203 unmodified lines
204struct bpf_subprog_info {204struct bpf_subprog_info {
205 u32 start; /* insn idx of function entry point */205 u32 start; /* insn idx of function entry point */
206 u16 stack_depth; /* max. stack depth used by this function */206 u16 stack_depth; /* max. stack depth used by this function */
207 u32 type_id; /* btf type_id for this subprog */
208};207};
209 208
210/* single container for all structs209/* single container for all structs
include/uapi/linux/bpf.h+15−1
@@ -2268,6 +2268,19 @@ union bpf_attr { · 2267 unmodified lines
2268 *2268 *
2269 * Return2269 * Return
2270 * 0 on success, or a negative error in case of failure.2270 * 0 on success, or a negative error in case of failure.
2271 *
2272 * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags)
2273 * Description
2274 * Will remove *pop* bytes from a *msg* starting at byte *start*.
2275 * This may result in **ENOMEM** errors under certain situations if
2276 * an allocation and copy are required due to a full ring buffer.
2277 * However, the helper will try to avoid doing the allocation
2278 * if possible. Other errors can occur if input parameters are
2279 * invalid either due to *start* byte not being valid part of msg
2280 * payload and/or *pop* value being to large.
2281 *
2282 * Return
2283 * 0 on success, or a negative erro in case of failure.
2271 */2284 */
2272#define __BPF_FUNC_MAPPER(FN) \2285#define __BPF_FUNC_MAPPER(FN) \
2273 FN(unspec), \2286 FN(unspec), \
@@ -2360,7 +2373,8 @@ union bpf_attr { · 86 unmodified lines
2360 FN(map_push_elem), \2373 FN(map_push_elem), \
2361 FN(map_pop_elem), \2374 FN(map_pop_elem), \
2362 FN(map_peek_elem), \2375 FN(map_peek_elem), \
2363 FN(msg_push_data),2376 FN(msg_push_data), \
2377 FN(msg_pop_data),
2364 2378
2365/* integer value in 'imm' field of BPF_CALL instruction selects which helper2379/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2366 * function eBPF program intends to call2380 * function eBPF program intends to call
kernel/bpf/core.c+2−1
@@ -411,7 +411,8 @@ static void bpf_get_prog_name(const struct bpf_prog *prog, char *sym) · 410 unmodified lines
411 411
412 /* prog->aux->name will be ignored if full btf name is available */412 /* prog->aux->name will be ignored if full btf name is available */
413 if (prog->aux->btf) {413 if (prog->aux->btf) {
414 type = btf_type_by_id(prog->aux->btf, prog->aux->type_id);414 type = btf_type_by_id(prog->aux->btf,
415 prog->aux->func_info[prog->aux->func_idx].type_id);
415 func_name = btf_name_by_offset(prog->aux->btf, type->name_off);416 func_name = btf_name_by_offset(prog->aux->btf, type->name_off);
416 snprintf(sym, (size_t)(end - sym), "_%s", func_name);417 snprintf(sym, (size_t)(end - sym), "_%s", func_name);
417 return;418 return;
kernel/bpf/syscall.c+8−25
@@ -1214,6 +1214,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) · 1213 unmodified lines
1214 bpf_prog_free_id(prog, do_idr_lock);1214 bpf_prog_free_id(prog, do_idr_lock);
1215 bpf_prog_kallsyms_del_all(prog);1215 bpf_prog_kallsyms_del_all(prog);
1216 btf_put(prog->aux->btf);1216 btf_put(prog->aux->btf);
1217 kvfree(prog->aux->func_info);
1217 1218
1218 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);1219 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1219 }1220 }
@@ -2219,46 +2220,28 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, · 999 unmodified lines
2219 }2220 }
2220 2221
2221 if (prog->aux->btf) {2222 if (prog->aux->btf) {
2223 u32 krec_size = sizeof(struct bpf_func_info);
2222 u32 ucnt, urec_size;2224 u32 ucnt, urec_size;
2223 2225
2224 info.btf_id = btf_id(prog->aux->btf);2226 info.btf_id = btf_id(prog->aux->btf);
2225 2227
2226 ucnt = info.func_info_cnt;2228 ucnt = info.func_info_cnt;
2227 info.func_info_cnt = prog->aux->func_cnt ? : 1;2229 info.func_info_cnt = prog->aux->func_info_cnt;
2228 urec_size = info.func_info_rec_size;2230 urec_size = info.func_info_rec_size;
2229 info.func_info_rec_size = sizeof(struct bpf_func_info);2231 info.func_info_rec_size = krec_size;
2230 if (ucnt) {2232 if (ucnt) {
2231 /* expect passed-in urec_size is what the kernel expects */2233 /* expect passed-in urec_size is what the kernel expects */
2232 if (urec_size != info.func_info_rec_size)2234 if (urec_size != info.func_info_rec_size)
2233 return -EINVAL;2235 return -EINVAL;
2234 2236
2235 if (bpf_dump_raw_ok()) {2237 if (bpf_dump_raw_ok()) {
2236 struct bpf_func_info kern_finfo;
2237 char __user *user_finfo;2238 char __user *user_finfo;
2238 u32 i, insn_offset;
2239 2239
2240 user_finfo = u64_to_user_ptr(info.func_info);2240 user_finfo = u64_to_user_ptr(info.func_info);
2241 if (prog->aux->func_cnt) {2241 ucnt = min_t(u32, info.func_info_cnt, ucnt);
2242 ucnt = min_t(u32, info.func_info_cnt, ucnt);2242 if (copy_to_user(user_finfo, prog->aux->func_info,
2243 insn_offset = 0;2243 krec_size * ucnt))
2244 for (i = 0; i < ucnt; i++) {2244 return -EFAULT;
2245 kern_finfo.insn_offset = insn_offset;
2246 kern_finfo.type_id = prog->aux->func[i]->aux->type_id;
2247 if (copy_to_user(user_finfo, &kern_finfo,
2248 sizeof(kern_finfo)))
2249 return -EFAULT;
2250
2251 /* func[i]->len holds the prog len */
2252 insn_offset += prog->aux->func[i]->len;
2253 user_finfo += urec_size;
2254 }
2255 } else {
2256 kern_finfo.insn_offset = 0;
2257 kern_finfo.type_id = prog->aux->type_id;
2258 if (copy_to_user(user_finfo, &kern_finfo,
2259 sizeof(kern_finfo)))
2260 return -EFAULT;
2261 }
2262 } else {2245 } else {
2263 info.func_info_cnt = 0;2246 info.func_info_cnt = 0;
2264 }2247 }
kernel/bpf/verifier.c+38−17
@@ -4650,7 +4650,7 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 4649 unmodified lines
4650{4650{
4651 u32 i, nfuncs, urec_size, min_size, prev_offset;4651 u32 i, nfuncs, urec_size, min_size, prev_offset;
4652 u32 krec_size = sizeof(struct bpf_func_info);4652 u32 krec_size = sizeof(struct bpf_func_info);
4653 struct bpf_func_info krecord = {};4653 struct bpf_func_info *krecord = NULL;
4654 const struct btf_type *type;4654 const struct btf_type *type;
4655 void __user *urecord;4655 void __user *urecord;
4656 struct btf *btf;4656 struct btf *btf;
@@ -4682,6 +4682,12 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 25 unmodified lines
4682 urecord = u64_to_user_ptr(attr->func_info);4682 urecord = u64_to_user_ptr(attr->func_info);
4683 min_size = min_t(u32, krec_size, urec_size);4683 min_size = min_t(u32, krec_size, urec_size);
4684 4684
4685 krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN);
4686 if (!krecord) {
4687 ret = -ENOMEM;
4688 goto free_btf;
4689 }
4690
4685 for (i = 0; i < nfuncs; i++) {4691 for (i = 0; i < nfuncs; i++) {
4686 ret = bpf_check_uarg_tail_zero(urecord, krec_size, urec_size);4692 ret = bpf_check_uarg_tail_zero(urecord, krec_size, urec_size);
4687 if (ret) {4693 if (ret) {
@@ -4696,59 +4702,69 @@ static int check_btf_func(struct bpf_prog *prog, struct bpf_verifier_env *env, · 8 unmodified lines
4696 goto free_btf;4702 goto free_btf;
4697 }4703 }
4698 4704
4699 if (copy_from_user(&krecord, urecord, min_size)) {4705 if (copy_from_user(&krecord[i], urecord, min_size)) {
4700 ret = -EFAULT;4706 ret = -EFAULT;
4701 goto free_btf;4707 goto free_btf;
4702 }4708 }
4703 4709
4704 /* check insn_offset */4710 /* check insn_offset */
4705 if (i == 0) {4711 if (i == 0) {
4706 if (krecord.insn_offset) {4712 if (krecord[i].insn_offset) {
4707 verbose(env,4713 verbose(env,
4708 "nonzero insn_offset %u for the first func info record",4714 "nonzero insn_offset %u for the first func info record",
4709 krecord.insn_offset);4715 krecord[i].insn_offset);
4710 ret = -EINVAL;4716 ret = -EINVAL;
4711 goto free_btf;4717 goto free_btf;
4712 }4718 }
4713 } else if (krecord.insn_offset <= prev_offset) {4719 } else if (krecord[i].insn_offset <= prev_offset) {
4714 verbose(env,4720 verbose(env,
4715 "same or smaller insn offset (%u) than previous func info record (%u)",4721 "same or smaller insn offset (%u) than previous func info record (%u)",
4716 krecord.insn_offset, prev_offset);4722 krecord[i].insn_offset, prev_offset);
4717 ret = -EINVAL;4723 ret = -EINVAL;
4718 goto free_btf;4724 goto free_btf;
4719 }4725 }
4720 4726
4721 if (env->subprog_info[i].start != krecord.insn_offset) {4727 if (env->subprog_info[i].start != krecord[i].insn_offset) {
4722 verbose(env, "func_info BTF section doesn't match subprog layout in BPF program\n");4728 verbose(env, "func_info BTF section doesn't match subprog layout in BPF program\n");
4723 ret = -EINVAL;4729 ret = -EINVAL;
4724 goto free_btf;4730 goto free_btf;
4725 }4731 }
4726 4732
4727 /* check type_id */4733 /* check type_id */
4728 type = btf_type_by_id(btf, krecord.type_id);4734 type = btf_type_by_id(btf, krecord[i].type_id);
4729 if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) {4735 if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) {
4730 verbose(env, "invalid type id %d in func info",4736 verbose(env, "invalid type id %d in func info",
4731 krecord.type_id);4737 krecord[i].type_id);
4732 ret = -EINVAL;4738 ret = -EINVAL;
4733 goto free_btf;4739 goto free_btf;
4734 }4740 }
4735 4741
4736 if (i == 0)4742 prev_offset = krecord[i].insn_offset;
4737 prog->aux->type_id = krecord.type_id;
4738 env->subprog_info[i].type_id = krecord.type_id;
4739
4740 prev_offset = krecord.insn_offset;
4741 urecord += urec_size;4743 urecord += urec_size;
4742 }4744 }
4743 4745
4744 prog->aux->btf = btf;4746 prog->aux->btf = btf;
4747 prog->aux->func_info = krecord;
4748 prog->aux->func_info_cnt = nfuncs;
4745 return 0;4749 return 0;
4746 4750
4747free_btf:4751free_btf:
4748 btf_put(btf);4752 btf_put(btf);
4753 kvfree(krecord);
4749 return ret;4754 return ret;
4750}4755}
4751 4756
4757static void adjust_btf_func(struct bpf_verifier_env *env)
4758{
4759 int i;
4760
4761 if (!env->prog->aux->func_info)
4762 return;
4763
4764 for (i = 0; i < env->subprog_cnt; i++)
4765 env->prog->aux->func_info[i].insn_offset = env->subprog_info[i].start;
4766}
4767
4752/* check %cur's range satisfies %old's */4768/* check %cur's range satisfies %old's */
4753static bool range_within(struct bpf_reg_state *old,4769static bool range_within(struct bpf_reg_state *old,
4754 struct bpf_reg_state *cur)4770 struct bpf_reg_state *cur)
@@ -6043,15 +6059,17 @@ static int jit_subprogs(struct bpf_verifier_env *env) · 1288 unmodified lines
6043 if (bpf_prog_calc_tag(func[i]))6059 if (bpf_prog_calc_tag(func[i]))
6044 goto out_free;6060 goto out_free;
6045 func[i]->is_func = 1;6061 func[i]->is_func = 1;
6062 func[i]->aux->func_idx = i;
6063 /* the btf and func_info will be freed only at prog->aux */
6064 func[i]->aux->btf = prog->aux->btf;
6065 func[i]->aux->func_info = prog->aux->func_info;
6066
6046 /* Use bpf_prog_F_tag to indicate functions in stack traces.6067 /* Use bpf_prog_F_tag to indicate functions in stack traces.
6047 * Long term would need debug info to populate names6068 * Long term would need debug info to populate names
6048 */6069 */
6049 func[i]->aux->name[0] = 'F';6070 func[i]->aux->name[0] = 'F';
6050 func[i]->aux->stack_depth = env->subprog_info[i].stack_depth;6071 func[i]->aux->stack_depth = env->subprog_info[i].stack_depth;
6051 func[i]->jit_requested = 1;6072 func[i]->jit_requested = 1;
6052 /* the btf will be freed only at prog->aux */
6053 func[i]->aux->btf = prog->aux->btf;
6054 func[i]->aux->type_id = env->subprog_info[i].type_id;
6055 func[i] = bpf_int_jit_compile(func[i]);6073 func[i] = bpf_int_jit_compile(func[i]);
6056 if (!func[i]->jited) {6074 if (!func[i]->jited) {
6057 err = -ENOTSUPP;6075 err = -ENOTSUPP;
@@ -6572,6 +6590,9 @@ skip_full_check: · 514 unmodified lines
6572 convert_pseudo_ld_imm64(env);6590 convert_pseudo_ld_imm64(env);
6573 }6591 }
6574 6592
6593 if (ret == 0)
6594 adjust_btf_func(env);
6595
6575err_release_maps:6596err_release_maps:
6576 if (!env->prog->aux->used_maps)6597 if (!env->prog->aux->used_maps)
6577 /* if we didn't copy map pointers into bpf_prog_info, release6598 /* if we didn't copy map pointers into bpf_prog_info, release
net/core/filter.c+173−1
@@ -463,7 +463,8 @@ static bool convert_bpf_ld_abs(struct sock_filter *fp, struct bpf_insn **insnp) · 462 unmodified lines
463 bool ldx_off_ok = offset <= S16_MAX;463 bool ldx_off_ok = offset <= S16_MAX;
464 464
465 *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_H);465 *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_H);
466 *insn++ = BPF_ALU64_IMM(BPF_SUB, BPF_REG_TMP, offset);466 if (offset)
467 *insn++ = BPF_ALU64_IMM(BPF_SUB, BPF_REG_TMP, offset);
467 *insn++ = BPF_JMP_IMM(BPF_JSLT, BPF_REG_TMP,468 *insn++ = BPF_JMP_IMM(BPF_JSLT, BPF_REG_TMP,
468 size, 2 + endian + (!ldx_off_ok * 2));469 size, 2 + endian + (!ldx_off_ok * 2));
469 if (ldx_off_ok) {470 if (ldx_off_ok) {
@@ -2424,6 +2425,174 @@ static const struct bpf_func_proto bpf_msg_push_data_proto = { · 1954 unmodified lines
2424 .arg4_type = ARG_ANYTHING,2425 .arg4_type = ARG_ANYTHING,
2425};2426};
2426 2427
2428static void sk_msg_shift_left(struct sk_msg *msg, int i)
2429{
2430 int prev;
2431
2432 do {
2433 prev = i;
2434 sk_msg_iter_var_next(i);
2435 msg->sg.data[prev] = msg->sg.data[i];
2436 } while (i != msg->sg.end);
2437
2438 sk_msg_iter_prev(msg, end);
2439}
2440
2441static void sk_msg_shift_right(struct sk_msg *msg, int i)
2442{
2443 struct scatterlist tmp, sge;
2444
2445 sk_msg_iter_next(msg, end);
2446 sge = sk_msg_elem_cpy(msg, i);
2447 sk_msg_iter_var_next(i);
2448 tmp = sk_msg_elem_cpy(msg, i);
2449
2450 while (i != msg->sg.end) {
2451 msg->sg.data[i] = sge;
2452 sk_msg_iter_var_next(i);
2453 sge = tmp;
2454 tmp = sk_msg_elem_cpy(msg, i);
2455 }
2456}
2457
2458BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
2459 u32, len, u64, flags)
2460{
2461 u32 i = 0, l, space, offset = 0;
2462 u64 last = start + len;
2463 int pop;
2464
2465 if (unlikely(flags))
2466 return -EINVAL;
2467
2468 /* First find the starting scatterlist element */
2469 i = msg->sg.start;
2470 do {
2471 l = sk_msg_elem(msg, i)->length;
2472
2473 if (start < offset + l)
2474 break;
2475 offset += l;
2476 sk_msg_iter_var_next(i);
2477 } while (i != msg->sg.end);
2478
2479 /* Bounds checks: start and pop must be inside message */
2480 if (start >= offset + l || last >= msg->sg.size)
2481 return -EINVAL;
2482
2483 space = MAX_MSG_FRAGS - sk_msg_elem_used(msg);
2484
2485 pop = len;
2486 /* --------------| offset
2487 * -| start |-------- len -------|
2488 *
2489 * |----- a ----|-------- pop -------|----- b ----|
2490 * |______________________________________________| length
2491 *
2492 *
2493 * a: region at front of scatter element to save
2494 * b: region at back of scatter element to save when length > A + pop
2495 * pop: region to pop from element, same as input 'pop' here will be
2496 * decremented below per iteration.
2497 *
2498 * Two top-level cases to handle when start != offset, first B is non
2499 * zero and second B is zero corresponding to when a pop includes more
2500 * than one element.
2501 *
2502 * Then if B is non-zero AND there is no space allocate space and
2503 * compact A, B regions into page. If there is space shift ring to
2504 * the rigth free'ing the next element in ring to place B, leaving
2505 * A untouched except to reduce length.
2506 */
2507 if (start != offset) {
2508 struct scatterlist *nsge, *sge = sk_msg_elem(msg, i);
2509 int a = start;
2510 int b = sge->length - pop - a;
2511
2512 sk_msg_iter_var_next(i);
2513
2514 if (pop < sge->length - a) {
2515 if (space) {
2516 sge->length = a;
2517 sk_msg_shift_right(msg, i);
2518 nsge = sk_msg_elem(msg, i);
2519 get_page(sg_page(sge));
2520 sg_set_page(nsge,
2521 sg_page(sge),
2522 b, sge->offset + pop + a);
2523 } else {
2524 struct page *page, *orig;
2525 u8 *to, *from;
2526
2527 page = alloc_pages(__GFP_NOWARN |
2528 __GFP_COMP | GFP_ATOMIC,
2529 get_order(a + b));
2530 if (unlikely(!page))
2531 return -ENOMEM;
2532
2533 sge->length = a;
2534 orig = sg_page(sge);
2535 from = sg_virt(sge);
2536 to = page_address(page);
2537 memcpy(to, from, a);
2538 memcpy(to + a, from + a + pop, b);
2539 sg_set_page(sge, page, a + b, 0);
2540 put_page(orig);
2541 }
2542 pop = 0;
2543 } else if (pop >= sge->length - a) {
2544 sge->length = a;
2545 pop -= (sge->length - a);
2546 }
2547 }
2548
2549 /* From above the current layout _must_ be as follows,
2550 *
2551 * -| offset
2552 * -| start
2553 *
2554 * |---- pop ---|---------------- b ------------|
2555 * |____________________________________________| length
2556 *
2557 * Offset and start of the current msg elem are equal because in the
2558 * previous case we handled offset != start and either consumed the
2559 * entire element and advanced to the next element OR pop == 0.
2560 *
2561 * Two cases to handle here are first pop is less than the length
2562 * leaving some remainder b above. Simply adjust the element's layout
2563 * in this case. Or pop >= length of the element so that b = 0. In this
2564 * case advance to next element decrementing pop.
2565 */
2566 while (pop) {
2567 struct scatterlist *sge = sk_msg_elem(msg, i);
2568
2569 if (pop < sge->length) {
2570 sge->length -= pop;
2571 sge->offset += pop;
2572 pop = 0;
2573 } else {
2574 pop -= sge->length;
2575 sk_msg_shift_left(msg, i);
2576 }
2577 sk_msg_iter_var_next(i);
2578 }
2579
2580 sk_mem_uncharge(msg->sk, len - pop);
2581 msg->sg.size -= (len - pop);
2582 sk_msg_compute_data_pointers(msg);
2583 return 0;
2584}
2585
2586static const struct bpf_func_proto bpf_msg_pop_data_proto = {
2587 .func = bpf_msg_pop_data,
2588 .gpl_only = false,
2589 .ret_type = RET_INTEGER,
2590 .arg1_type = ARG_PTR_TO_CTX,
2591 .arg2_type = ARG_ANYTHING,
2592 .arg3_type = ARG_ANYTHING,
2593 .arg4_type = ARG_ANYTHING,
2594};
2595
2427BPF_CALL_1(bpf_get_cgroup_classid, const struct sk_buff *, skb)2596BPF_CALL_1(bpf_get_cgroup_classid, const struct sk_buff *, skb)
2428{2597{
2429 return task_get_classid(skb);2598 return task_get_classid(skb);
@@ -5097,6 +5266,7 @@ bool bpf_helper_changes_pkt_data(void *func) · 2667 unmodified lines
5097 func == bpf_xdp_adjust_meta ||5266 func == bpf_xdp_adjust_meta ||
5098 func == bpf_msg_pull_data ||5267 func == bpf_msg_pull_data ||
5099 func == bpf_msg_push_data ||5268 func == bpf_msg_push_data ||
5269 func == bpf_msg_pop_data ||
5100 func == bpf_xdp_adjust_tail ||5270 func == bpf_xdp_adjust_tail ||
5101#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)5271#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
5102 func == bpf_lwt_seg6_store_bytes ||5272 func == bpf_lwt_seg6_store_bytes ||
@@ -5393,6 +5563,8 @@ sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 290 unmodified lines
5393 return &bpf_msg_pull_data_proto;5563 return &bpf_msg_pull_data_proto;
5394 case BPF_FUNC_msg_push_data:5564 case BPF_FUNC_msg_push_data:
5395 return &bpf_msg_push_data_proto;5565 return &bpf_msg_push_data_proto;
5566 case BPF_FUNC_msg_pop_data:
5567 return &bpf_msg_pop_data_proto;
5396 default:5568 default:
5397 return bpf_base_func_proto(func_id);5569 return bpf_base_func_proto(func_id);
5398 }5570 }
net/ipv4/tcp_bpf.c+14−3
@@ -289,12 +289,23 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, · 288 unmodified lines
289{289{
290 bool cork = false, enospc = msg->sg.start == msg->sg.end;290 bool cork = false, enospc = msg->sg.start == msg->sg.end;
291 struct sock *sk_redir;291 struct sock *sk_redir;
292 u32 tosend;292 u32 tosend, delta = 0;
293 int ret;293 int ret;
294 294
295more_data:295more_data:
296 if (psock->eval == __SK_NONE)296 if (psock->eval == __SK_NONE) {
297 /* Track delta in msg size to add/subtract it on SK_DROP from
298 * returned to user copied size. This ensures user doesn't
299 * get a positive return code with msg_cut_data and SK_DROP
300 * verdict.
301 */
302 delta = msg->sg.size;
297 psock->eval = sk_psock_msg_verdict(sk, psock, msg);303 psock->eval = sk_psock_msg_verdict(sk, psock, msg);
304 if (msg->sg.size < delta)
305 delta -= msg->sg.size;
306 else
307 delta = 0;
308 }
298 309
299 if (msg->cork_bytes &&310 if (msg->cork_bytes &&
300 msg->cork_bytes > msg->sg.size && !enospc) {311 msg->cork_bytes > msg->sg.size && !enospc) {
@@ -350,7 +361,7 @@ more_data: · 49 unmodified lines
350 default:361 default:
351 sk_msg_free_partial(sk, msg, tosend);362 sk_msg_free_partial(sk, msg, tosend);
352 sk_msg_apply_bytes(psock, tosend);363 sk_msg_apply_bytes(psock, tosend);
353 *copied -= tosend;364 *copied -= (tosend + delta);
354 return -EACCES;365 return -EACCES;
355 }366 }
356 367
net/tls/tls_sw.c+9−2
@@ -687,6 +687,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, · 686 unmodified lines
687 struct sock *sk_redir;687 struct sock *sk_redir;
688 struct tls_rec *rec;688 struct tls_rec *rec;
689 int err = 0, send;689 int err = 0, send;
690 u32 delta = 0;
690 bool enospc;691 bool enospc;
691 692
692 psock = sk_psock_get(sk);693 psock = sk_psock_get(sk);
@@ -694,8 +695,14 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, · 1 unmodified line
694 return tls_push_record(sk, flags, record_type);695 return tls_push_record(sk, flags, record_type);
695more_data:696more_data:
696 enospc = sk_msg_full(msg);697 enospc = sk_msg_full(msg);
697 if (psock->eval == __SK_NONE)698 if (psock->eval == __SK_NONE) {
699 delta = msg->sg.size;
698 psock->eval = sk_psock_msg_verdict(sk, psock, msg);700 psock->eval = sk_psock_msg_verdict(sk, psock, msg);
701 if (delta < msg->sg.size)
702 delta -= msg->sg.size;
703 else
704 delta = 0;
705 }
699 if (msg->cork_bytes && msg->cork_bytes > msg->sg.size &&706 if (msg->cork_bytes && msg->cork_bytes > msg->sg.size &&
700 !enospc && !full_record) {707 !enospc && !full_record) {
701 err = -ENOSPC;708 err = -ENOSPC;
@@ -743,7 +750,7 @@ more_data: · 41 unmodified lines
743 msg->apply_bytes -= send;750 msg->apply_bytes -= send;
744 if (msg->sg.size == 0)751 if (msg->sg.size == 0)
745 tls_free_open_rec(sk);752 tls_free_open_rec(sk);
746 *copied -= send;753 *copied -= (send + delta);
747 err = -EACCES;754 err = -EACCES;
748 }755 }
749 756
tools/bpf/bpftool/map.c+2−2
@@ -713,7 +713,7 @@ static int do_dump(int argc, char **argv) · 712 unmodified lines
713 713
714 prev_key = NULL;714 prev_key = NULL;
715 715
716 err = btf_get_from_id(info.btf_id, &btf);716 err = btf__get_from_id(info.btf_id, &btf);
717 if (err) {717 if (err) {
718 p_err("failed to get btf");718 p_err("failed to get btf");
719 goto exit_free;719 goto exit_free;
@@ -857,7 +857,7 @@ static int do_lookup(int argc, char **argv) · 137 unmodified lines
857 }857 }
858 858
859 /* here means bpf_map_lookup_elem() succeeded */859 /* here means bpf_map_lookup_elem() succeeded */
860 err = btf_get_from_id(info.btf_id, &btf);860 err = btf__get_from_id(info.btf_id, &btf);
861 if (err) {861 if (err) {
862 p_err("failed to get btf");862 p_err("failed to get btf");
863 goto exit_free;863 goto exit_free;
tools/bpf/bpftool/prog.c+1−1
@@ -621,7 +621,7 @@ static int do_dump(int argc, char **argv) · 620 unmodified lines
621 goto err_free;621 goto err_free;
622 }622 }
623 623
624 if (info.btf_id && btf_get_from_id(info.btf_id, &btf)) {624 if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) {
625 p_err("failed to get btf");625 p_err("failed to get btf");
626 goto err_free;626 goto err_free;
627 }627 }
tools/include/uapi/linux/bpf.h+15−1
@@ -2268,6 +2268,19 @@ union bpf_attr { · 2267 unmodified lines
2268 *2268 *
2269 * Return2269 * Return
2270 * 0 on success, or a negative error in case of failure.2270 * 0 on success, or a negative error in case of failure.
2271 *
2272 * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags)
2273 * Description
2274 * Will remove *pop* bytes from a *msg* starting at byte *start*.
2275 * This may result in **ENOMEM** errors under certain situations if
2276 * an allocation and copy are required due to a full ring buffer.
2277 * However, the helper will try to avoid doing the allocation
2278 * if possible. Other errors can occur if input parameters are
2279 * invalid either due to *start* byte not being valid part of msg
2280 * payload and/or *pop* value being to large.
2281 *
2282 * Return
2283 * 0 on success, or a negative erro in case of failure.
2271 */2284 */
2272#define __BPF_FUNC_MAPPER(FN) \2285#define __BPF_FUNC_MAPPER(FN) \
2273 FN(unspec), \2286 FN(unspec), \
@@ -2360,7 +2373,8 @@ union bpf_attr { · 86 unmodified lines
2360 FN(map_push_elem), \2373 FN(map_push_elem), \
2361 FN(map_pop_elem), \2374 FN(map_pop_elem), \
2362 FN(map_peek_elem), \2375 FN(map_peek_elem), \
2363 FN(msg_push_data),2376 FN(msg_push_data), \
2377 FN(msg_pop_data),
2364 2378
2365/* integer value in 'imm' field of BPF_CALL instruction selects which helper2379/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2366 * function eBPF program intends to call2380 * function eBPF program intends to call
tools/lib/bpf/Makefile+21−2
@@ -145,6 +145,12 @@ include $(srctree)/tools/build/Makefile.include · 144 unmodified lines
145 145
146BPF_IN := $(OUTPUT)libbpf-in.o146BPF_IN := $(OUTPUT)libbpf-in.o
147LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))147LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
148VERSION_SCRIPT := libbpf.map
149
150GLOBAL_SYM_COUNT = $(shell readelf -s $(BPF_IN) | \
151 awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}')
152VERSIONED_SYM_COUNT = $(shell readelf -s $(OUTPUT)libbpf.so | \
153 grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
148 154
149CMD_TARGETS = $(LIB_FILE)155CMD_TARGETS = $(LIB_FILE)
150 156
@@ -158,7 +164,7 @@ TARGETS = $(CMD_TARGETS) · 7 unmodified lines
158 164
159all: fixdep all_cmd165all: fixdep all_cmd
160 166
161all_cmd: $(CMD_TARGETS)167all_cmd: $(CMD_TARGETS) check
162 168
163$(BPF_IN): force elfdep bpfdep169$(BPF_IN): force elfdep bpfdep
164 @(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \170 @(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
@@ -176,7 +182,8 @@ $(BPF_IN): force elfdep bpfdep · 11 unmodified lines
176 $(Q)$(MAKE) $(build)=libbpf182 $(Q)$(MAKE) $(build)=libbpf
177 183
178$(OUTPUT)libbpf.so: $(BPF_IN)184$(OUTPUT)libbpf.so: $(BPF_IN)
179 $(QUIET_LINK)$(CC) --shared $^ -o $@185 $(QUIET_LINK)$(CC) --shared -Wl,--version-script=$(VERSION_SCRIPT) \
186 $^ -o $@
180 187
181$(OUTPUT)libbpf.a: $(BPF_IN)188$(OUTPUT)libbpf.a: $(BPF_IN)
182 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^189 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
@@ -184,6 +191,18 @@ $(OUTPUT)libbpf.a: $(BPF_IN) · 1 unmodified line
184$(OUTPUT)test_libbpf: test_libbpf.cpp $(OUTPUT)libbpf.a191$(OUTPUT)test_libbpf: test_libbpf.cpp $(OUTPUT)libbpf.a
185 $(QUIET_LINK)$(CXX) $^ -lelf -o $@192 $(QUIET_LINK)$(CXX) $^ -lelf -o $@
186 193
194check: check_abi
195
196check_abi: $(OUTPUT)libbpf.so
197 @if [ "$(GLOBAL_SYM_COUNT)" != "$(VERSIONED_SYM_COUNT)" ]; then \
198 echo "Warning: Num of global symbols in $(BPF_IN)" \
199 "($(GLOBAL_SYM_COUNT)) does NOT match with num of" \
200 "versioned symbols in $^ ($(VERSIONED_SYM_COUNT))." \
201 "Please make sure all LIBBPF_API symbols are" \
202 "versioned in $(VERSION_SCRIPT)." >&2; \
203 exit 1; \
204 fi
205
187define do_install206define do_install
188 if [ ! -d '$(DESTDIR_SQ)$2' ]; then \207 if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
189 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \208 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
tools/lib/bpf/README.rst+139−0
@@ -0,0 +1,139 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3libbpf API naming convention
4============================
5
6libbpf API provides access to a few logically separated groups of
7functions and types. Every group has its own naming convention
8described here. It's recommended to follow these conventions whenever a
9new function or type is added to keep libbpf API clean and consistent.
10
11All types and functions provided by libbpf API should have one of the
12following prefixes: ``bpf_``, ``btf_``, ``libbpf_``.
13
14System call wrappers
15--------------------
16
17System call wrappers are simple wrappers for commands supported by
18sys_bpf system call. These wrappers should go to ``bpf.h`` header file
19and map one-on-one to corresponding commands.
20
21For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM``
22command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc.
23
24Objects
25-------
26
27Another class of types and functions provided by libbpf API is "objects"
28and functions to work with them. Objects are high-level abstractions
29such as BPF program or BPF map. They're represented by corresponding
30structures such as ``struct bpf_object``, ``struct bpf_program``,
31``struct bpf_map``, etc.
32
33Structures are forward declared and access to their fields should be
34provided via corresponding getters and setters rather than directly.
35
36These objects are associated with corresponding parts of ELF object that
37contains compiled BPF programs.
38
39For example ``struct bpf_object`` represents ELF object itself created
40from an ELF file or from a buffer, ``struct bpf_program`` represents a
41program in ELF object and ``struct bpf_map`` is a map.
42
43Functions that work with an object have names built from object name,
44double underscore and part that describes function purpose.
45
46For example ``bpf_object__open`` consists of the name of corresponding
47object, ``bpf_object``, double underscore and ``open`` that defines the
48purpose of the function to open ELF file and create ``bpf_object`` from
49it.
50
51Another example: ``bpf_program__load`` is named for corresponding
52object, ``bpf_program``, that is separated from other part of the name
53by double underscore.
54
55All objects and corresponding functions other than BTF related should go
56to ``libbpf.h``. BTF types and functions should go to ``btf.h``.
57
58Auxiliary functions
59-------------------
60
61Auxiliary functions and types that don't fit well in any of categories
62described above should have ``libbpf_`` prefix, e.g.
63``libbpf_get_error`` or ``libbpf_prog_type_by_name``.
64
65libbpf ABI
66==========
67
68libbpf can be both linked statically or used as DSO. To avoid possible
69conflicts with other libraries an application is linked with, all
70non-static libbpf symbols should have one of the prefixes mentioned in
71API documentation above. See API naming convention to choose the right
72name for a new symbol.
73
74Symbol visibility
75-----------------
76
77libbpf follow the model when all global symbols have visibility "hidden"
78by default and to make a symbol visible it has to be explicitly
79attributed with ``LIBBPF_API`` macro. For example:
80
81.. code-block:: c
82
83 LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
84
85This prevents from accidentally exporting a symbol, that is not supposed
86to be a part of ABI what, in turn, improves both libbpf developer- and
87user-experiences.
88
89ABI versionning
90---------------
91
92To make future ABI extensions possible libbpf ABI is versioned.
93Versioning is implemented by ``libbpf.map`` version script that is
94passed to linker.
95
96Version name is ``LIBBPF_`` prefix + three-component numeric version,
97starting from ``0.0.1``.
98
99Every time ABI is being changed, e.g. because a new symbol is added or
100semantic of existing symbol is changed, ABI version should be bumped.
101
102For example, if current state of ``libbpf.map`` is:
103
104.. code-block::
105 LIBBPF_0.0.1 {
106 global:
107 bpf_func_a;
108 bpf_func_b;
109 local:
110 \*;
111 };
112
113, and a new symbol ``bpf_func_c`` is being introduced, then
114``libbpf.map`` should be changed like this:
115
116.. code-block::
117 LIBBPF_0.0.1 {
118 global:
119 bpf_func_a;
120 bpf_func_b;
121 local:
122 \*;
123 };
124 LIBBPF_0.0.2 {
125 global:
126 bpf_func_c;
127 } LIBBPF_0.0.1;
128
129, where new version ``LIBBPF_0.0.2`` depends on the previous
130``LIBBPF_0.0.1``.
131
132Format of version script and ways to handle ABI changes, including
133incompatible ones, described in details in [1].
134
135Links
136=====
137
138[1] https://www.akkadia.org/drepper/dsohowto.pdf
139 (Chapter 3. Maintaining APIs and ABIs).
tools/lib/bpf/btf.c+2−2
@@ -415,7 +415,7 @@ const char *btf__name_by_offset(const struct btf *btf, __u32 offset) · 414 unmodified lines
415 return NULL;415 return NULL;
416}416}
417 417
418int btf_get_from_id(__u32 id, struct btf **btf)418int btf__get_from_id(__u32 id, struct btf **btf)
419{419{
420 struct bpf_btf_info btf_info = { 0 };420 struct bpf_btf_info btf_info = { 0 };
421 __u32 len = sizeof(btf_info);421 __u32 len = sizeof(btf_info);
@@ -466,7 +466,7 @@ int btf_get_from_id(__u32 id, struct btf **btf) · 44 unmodified lines
466 goto exit_free;466 goto exit_free;
467 }467 }
468 468
469 *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);469 *btf = btf__new((__u8 *)(long)btf_info.btf, btf_info.btf_size, NULL);
470 if (IS_ERR(*btf)) {470 if (IS_ERR(*btf)) {
471 err = PTR_ERR(*btf);471 err = PTR_ERR(*btf);
472 *btf = NULL;472 *btf = NULL;
tools/lib/bpf/btf.h+1−1
@@ -73,7 +73,7 @@ LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id); · 72 unmodified lines
73LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);73LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
74LIBBPF_API int btf__fd(const struct btf *btf);74LIBBPF_API int btf__fd(const struct btf *btf);
75LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);75LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
76LIBBPF_API int btf_get_from_id(__u32 id, struct btf **btf);76LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
77 77
78struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);78struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
79void btf_ext__free(struct btf_ext *btf_ext);79void btf_ext__free(struct btf_ext *btf_ext);
tools/lib/bpf/libbpf.c+2−0
@@ -9,7 +9,9 @@ · 8 unmodified lines
9 * Copyright (C) 2017 Nicira, Inc.9 * Copyright (C) 2017 Nicira, Inc.
10 */10 */
11 11
12#ifndef _GNU_SOURCE
12#define _GNU_SOURCE13#define _GNU_SOURCE
14#endif
13#include <stdlib.h>15#include <stdlib.h>
14#include <stdio.h>16#include <stdio.h>
15#include <stdarg.h>17#include <stdarg.h>
tools/lib/bpf/libbpf.map+121−0
@@ -0,0 +1,121 @@
1LIBBPF_0.0.1 {
2 global:
3 bpf_btf_get_fd_by_id;
4 bpf_create_map;
5 bpf_create_map_in_map;
6 bpf_create_map_in_map_node;
7 bpf_create_map_name;
8 bpf_create_map_node;
9 bpf_create_map_xattr;
10 bpf_load_btf;
11 bpf_load_program;
12 bpf_load_program_xattr;
13 bpf_map__btf_key_type_id;
14 bpf_map__btf_value_type_id;
15 bpf_map__def;
16 bpf_map__fd;
17 bpf_map__is_offload_neutral;
18 bpf_map__name;
19 bpf_map__next;
20 bpf_map__pin;
21 bpf_map__prev;
22 bpf_map__priv;
23 bpf_map__reuse_fd;
24 bpf_map__set_ifindex;
25 bpf_map__set_inner_map_fd;
26 bpf_map__set_priv;
27 bpf_map__unpin;
28 bpf_map_delete_elem;
29 bpf_map_get_fd_by_id;
30 bpf_map_get_next_id;
31 bpf_map_get_next_key;
32 bpf_map_lookup_and_delete_elem;
33 bpf_map_lookup_elem;
34 bpf_map_update_elem;
35 bpf_obj_get;
36 bpf_obj_get_info_by_fd;
37 bpf_obj_pin;
38 bpf_object__btf_fd;
39 bpf_object__close;
40 bpf_object__find_map_by_name;
41 bpf_object__find_map_by_offset;
42 bpf_object__find_program_by_title;
43 bpf_object__kversion;
44 bpf_object__load;
45 bpf_object__name;
46 bpf_object__next;
47 bpf_object__open;
48 bpf_object__open_buffer;
49 bpf_object__open_xattr;
50 bpf_object__pin;
51 bpf_object__pin_maps;
52 bpf_object__pin_programs;
53 bpf_object__priv;
54 bpf_object__set_priv;
55 bpf_object__unload;
56 bpf_object__unpin_maps;
57 bpf_object__unpin_programs;
58 bpf_perf_event_read_simple;
59 bpf_prog_attach;
60 bpf_prog_detach;
61 bpf_prog_detach2;
62 bpf_prog_get_fd_by_id;
63 bpf_prog_get_next_id;
64 bpf_prog_load;
65 bpf_prog_load_xattr;
66 bpf_prog_query;
67 bpf_prog_test_run;
68 bpf_program__fd;
69 bpf_program__is_kprobe;
70 bpf_program__is_perf_event;
71 bpf_program__is_raw_tracepoint;
72 bpf_program__is_sched_act;
73 bpf_program__is_sched_cls;
74 bpf_program__is_socket_filter;
75 bpf_program__is_tracepoint;
76 bpf_program__is_xdp;
77 bpf_program__load;
78 bpf_program__next;
79 bpf_program__nth_fd;
80 bpf_program__pin;
81 bpf_program__pin_instance;
82 bpf_program__prev;
83 bpf_program__priv;
84 bpf_program__set_expected_attach_type;
85 bpf_program__set_ifindex;
86 bpf_program__set_kprobe;
87 bpf_program__set_perf_event;
88 bpf_program__set_prep;
89 bpf_program__set_priv;
90 bpf_program__set_raw_tracepoint;
91 bpf_program__set_sched_act;
92 bpf_program__set_sched_cls;
93 bpf_program__set_socket_filter;
94 bpf_program__set_tracepoint;
95 bpf_program__set_type;
96 bpf_program__set_xdp;
97 bpf_program__title;
98 bpf_program__unload;
99 bpf_program__unpin;
100 bpf_program__unpin_instance;
101 bpf_raw_tracepoint_open;
102 bpf_set_link_xdp_fd;
103 bpf_task_fd_query;
104 bpf_verify_program;
105 btf__fd;
106 btf__find_by_name;
107 btf__free;
108 btf__get_from_id;
109 btf__name_by_offset;
110 btf__new;
111 btf__resolve_size;
112 btf__resolve_type;
113 btf__type_by_id;
114 libbpf_attach_type_by_name;
115 libbpf_get_error;
116 libbpf_prog_type_by_name;
117 libbpf_set_print;
118 libbpf_strerror;
119 local:
120 *;
121};
tools/lib/bpf/libbpf_errno.c+1−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
7 * Copyright (C) 2017 Nicira, Inc.7 * Copyright (C) 2017 Nicira, Inc.
8 */8 */
9 9
10#undef _GNU_SOURCE
10#include <stdio.h>11#include <stdio.h>
11#include <string.h>12#include <string.h>
12 13
tools/testing/selftests/bpf/bpf_helpers.h+2−0
@@ -113,6 +113,8 @@ static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) = · 112 unmodified lines
113 (void *) BPF_FUNC_msg_pull_data;113 (void *) BPF_FUNC_msg_pull_data;
114static int (*bpf_msg_push_data)(void *ctx, int start, int end, int flags) =114static int (*bpf_msg_push_data)(void *ctx, int start, int end, int flags) =
115 (void *) BPF_FUNC_msg_push_data;115 (void *) BPF_FUNC_msg_push_data;
116static int (*bpf_msg_pop_data)(void *ctx, int start, int cut, int flags) =
117 (void *) BPF_FUNC_msg_pop_data;
116static int (*bpf_bind)(void *ctx, void *addr, int addr_len) =118static int (*bpf_bind)(void *ctx, void *addr, int addr_len) =
117 (void *) BPF_FUNC_bind;119 (void *) BPF_FUNC_bind;
118static int (*bpf_xdp_adjust_tail)(void *ctx, int offset) =120static int (*bpf_xdp_adjust_tail)(void *ctx, int offset) =
tools/testing/selftests/bpf/config+1−0
@@ -22,3 +22,4 @@ CONFIG_NET_CLS_FLOWER=m · 21 unmodified lines
22CONFIG_LWTUNNEL=y22CONFIG_LWTUNNEL=y
23CONFIG_BPF_STREAM_PARSER=y23CONFIG_BPF_STREAM_PARSER=y
24CONFIG_XDP_SOCKETS=y24CONFIG_XDP_SOCKETS=y
25CONFIG_FTRACE_SYSCALLS=y
tools/testing/selftests/bpf/test_btf.c+4−31
@@ -29,7 +29,6 @@ · 28 unmodified lines
29static uint32_t pass_cnt;29static uint32_t pass_cnt;
30static uint32_t error_cnt;30static uint32_t error_cnt;
31static uint32_t skip_cnt;31static uint32_t skip_cnt;
32static bool jit_enabled;
33 32
34#define CHECK(condition, format...) ({ \33#define CHECK(condition, format...) ({ \
35 int __ret = !!(condition); \34 int __ret = !!(condition); \
@@ -65,24 +64,6 @@ static int __base_pr(const char *format, ...) · 29 unmodified lines
65 return err;64 return err;
66}65}
67 66
68static bool is_jit_enabled(void)
69{
70 const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
71 bool enabled = false;
72 int sysctl_fd;
73
74 sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
75 if (sysctl_fd != -1) {
76 char tmpc;
77
78 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
79 enabled = (tmpc != '0');
80 close(sysctl_fd);
81 }
82
83 return enabled;
84}
85
86#define BTF_INFO_ENC(kind, root, vlen) \67#define BTF_INFO_ENC(kind, root, vlen) \
87 ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))68 ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
88 69
@@ -2547,8 +2528,8 @@ static int do_test_file(unsigned int test_num) · 2458 unmodified lines
2547 test->btf_kv_notfound))2528 test->btf_kv_notfound))
2548 goto done;2529 goto done;
2549 2530
2550 if (!jit_enabled || !has_btf_ext)2531 if (!has_btf_ext)
2551 goto skip_jit;2532 goto skip;
2552 2533
2553 /* get necessary program info */2534 /* get necessary program info */
2554 info_len = sizeof(struct bpf_prog_info);2535 info_len = sizeof(struct bpf_prog_info);
@@ -2604,7 +2585,7 @@ static int do_test_file(unsigned int test_num) · 49 unmodified lines
2604 goto done;2585 goto done;
2605 }2586 }
2606 2587
2607 err = btf_get_from_id(info.btf_id, &btf);2588 err = btf__get_from_id(info.btf_id, &btf);
2608 if (CHECK(err, "cannot get btf from kernel, err: %d", err))2589 if (CHECK(err, "cannot get btf from kernel, err: %d", err))
2609 goto done;2590 goto done;
2610 2591
@@ -2636,7 +2617,7 @@ static int do_test_file(unsigned int test_num) · 25 unmodified lines
2636 finfo = (void *)finfo + rec_size;2617 finfo = (void *)finfo + rec_size;
2637 }2618 }
2638 2619
2639skip_jit:2620skip:
2640 fprintf(stderr, "OK");2621 fprintf(stderr, "OK");
2641 2622
2642done:2623done:
@@ -3270,12 +3251,6 @@ static int do_test_func_type(int test_num) · 627 unmodified lines
3270 err = -1;3251 err = -1;
3271 goto done;3252 goto done;
3272 }3253 }
3273 if (!jit_enabled) {
3274 skip_cnt++;
3275 fprintf(stderr, "SKIPPED, please enable sysctl bpf_jit_enable\n");
3276 err = 0;
3277 goto done;
3278 }
3279 3254
3280 /* get necessary lens */3255 /* get necessary lens */
3281 info_len = sizeof(struct bpf_prog_info);3256 info_len = sizeof(struct bpf_prog_info);
@@ -3452,8 +3427,6 @@ int main(int argc, char **argv) · 170 unmodified lines
3452 if (args.always_log)3427 if (args.always_log)
3453 libbpf_set_print(__base_pr, __base_pr, __base_pr);3428 libbpf_set_print(__base_pr, __base_pr, __base_pr);
3454 3429
3455 jit_enabled = is_jit_enabled();
3456
3457 if (args.raw_test)3430 if (args.raw_test)
3458 err |= test_raw();3431 err |= test_raw();
3459 3432
tools/testing/selftests/bpf/test_progs.c+5−5
@@ -524,7 +524,7 @@ static void test_bpf_obj_id(void) · 523 unmodified lines
524 load_time < now - 60 || load_time > now + 60 ||524 load_time < now - 60 || load_time > now + 60 ||
525 prog_infos[i].created_by_uid != my_uid ||525 prog_infos[i].created_by_uid != my_uid ||
526 prog_infos[i].nr_map_ids != 1 ||526 prog_infos[i].nr_map_ids != 1 ||
527 *(int *)prog_infos[i].map_ids != map_infos[i].id ||527 *(int *)(long)prog_infos[i].map_ids != map_infos[i].id ||
528 strcmp((char *)prog_infos[i].name, expected_prog_name),528 strcmp((char *)prog_infos[i].name, expected_prog_name),
529 "get-prog-info(fd)",529 "get-prog-info(fd)",
530 "err %d errno %d i %d type %d(%d) info_len %u(%Zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",530 "err %d errno %d i %d type %d(%d) info_len %u(%Zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",
@@ -539,7 +539,7 @@ static void test_bpf_obj_id(void) · 8 unmodified lines
539 load_time, now,539 load_time, now,
540 prog_infos[i].created_by_uid, my_uid,540 prog_infos[i].created_by_uid, my_uid,
541 prog_infos[i].nr_map_ids, 1,541 prog_infos[i].nr_map_ids, 1,
542 *(int *)prog_infos[i].map_ids, map_infos[i].id,542 *(int *)(long)prog_infos[i].map_ids, map_infos[i].id,
543 prog_infos[i].name, expected_prog_name))543 prog_infos[i].name, expected_prog_name))
544 goto done;544 goto done;
545 }545 }
@@ -585,7 +585,7 @@ static void test_bpf_obj_id(void) · 39 unmodified lines
585 bzero(&prog_info, sizeof(prog_info));585 bzero(&prog_info, sizeof(prog_info));
586 info_len = sizeof(prog_info);586 info_len = sizeof(prog_info);
587 587
588 saved_map_id = *(int *)(prog_infos[i].map_ids);588 saved_map_id = *(int *)((long)prog_infos[i].map_ids);
589 prog_info.map_ids = prog_infos[i].map_ids;589 prog_info.map_ids = prog_infos[i].map_ids;
590 prog_info.nr_map_ids = 2;590 prog_info.nr_map_ids = 2;
591 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);591 err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len);
@@ -593,12 +593,12 @@ static void test_bpf_obj_id(void) · 1 unmodified line
593 prog_infos[i].xlated_prog_insns = 0;593 prog_infos[i].xlated_prog_insns = 0;
594 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||594 CHECK(err || info_len != sizeof(struct bpf_prog_info) ||
595 memcmp(&prog_info, &prog_infos[i], info_len) ||595 memcmp(&prog_info, &prog_infos[i], info_len) ||
596 *(int *)prog_info.map_ids != saved_map_id,596 *(int *)(long)prog_info.map_ids != saved_map_id,
597 "get-prog-info(next_id->fd)",597 "get-prog-info(next_id->fd)",
598 "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n",598 "err %d errno %d info_len %u(%Zu) memcmp %d map_id %u(%u)\n",
599 err, errno, info_len, sizeof(struct bpf_prog_info),599 err, errno, info_len, sizeof(struct bpf_prog_info),
600 memcmp(&prog_info, &prog_infos[i], info_len),600 memcmp(&prog_info, &prog_infos[i], info_len),
601 *(int *)prog_info.map_ids, saved_map_id);601 *(int *)(long)prog_info.map_ids, saved_map_id);
602 close(prog_fd);602 close(prog_fd);
603 }603 }
604 CHECK(nr_id_found != nr_iters,604 CHECK(nr_id_found != nr_iters,
tools/testing/selftests/bpf/test_sockmap.c+123−4
@@ -79,6 +79,8 @@ int txmsg_start; · 78 unmodified lines
79int txmsg_end;79int txmsg_end;
80int txmsg_start_push;80int txmsg_start_push;
81int txmsg_end_push;81int txmsg_end_push;
82int txmsg_start_pop;
83int txmsg_pop;
82int txmsg_ingress;84int txmsg_ingress;
83int txmsg_skb;85int txmsg_skb;
84int ktls;86int ktls;
@@ -104,6 +106,8 @@ static const struct option long_options[] = { · 19 unmodified lines
104 {"txmsg_end", required_argument, NULL, 'e'},106 {"txmsg_end", required_argument, NULL, 'e'},
105 {"txmsg_start_push", required_argument, NULL, 'p'},107 {"txmsg_start_push", required_argument, NULL, 'p'},
106 {"txmsg_end_push", required_argument, NULL, 'q'},108 {"txmsg_end_push", required_argument, NULL, 'q'},
109 {"txmsg_start_pop", required_argument, NULL, 'w'},
110 {"txmsg_pop", required_argument, NULL, 'x'},
107 {"txmsg_ingress", no_argument, &txmsg_ingress, 1 },111 {"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
108 {"txmsg_skb", no_argument, &txmsg_skb, 1 },112 {"txmsg_skb", no_argument, &txmsg_skb, 1 },
109 {"ktls", no_argument, &ktls, 1 },113 {"ktls", no_argument, &ktls, 1 },
@@ -473,13 +477,27 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, · 363 unmodified lines
473 clock_gettime(CLOCK_MONOTONIC, &s->end);477 clock_gettime(CLOCK_MONOTONIC, &s->end);
474 } else {478 } else {
475 int slct, recvp = 0, recv, max_fd = fd;479 int slct, recvp = 0, recv, max_fd = fd;
480 float total_bytes, txmsg_pop_total;
476 int fd_flags = O_NONBLOCK;481 int fd_flags = O_NONBLOCK;
477 struct timeval timeout;482 struct timeval timeout;
478 float total_bytes;
479 fd_set w;483 fd_set w;
480 484
481 fcntl(fd, fd_flags);485 fcntl(fd, fd_flags);
486 /* Account for pop bytes noting each iteration of apply will
487 * call msg_pop_data helper so we need to account for this
488 * by calculating the number of apply iterations. Note user
489 * of the tool can create cases where no data is sent by
490 * manipulating pop/push/pull/etc. For example txmsg_apply 1
491 * with txmsg_pop 1 will try to apply 1B at a time but each
492 * iteration will then pop 1B so no data will ever be sent.
493 * This is really only useful for testing edge cases in code
494 * paths.
495 */
482 total_bytes = (float)iov_count * (float)iov_length * (float)cnt;496 total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
497 txmsg_pop_total = txmsg_pop;
498 if (txmsg_apply)
499 txmsg_pop_total *= (total_bytes / txmsg_apply);
500 total_bytes -= txmsg_pop_total;
483 err = clock_gettime(CLOCK_MONOTONIC, &s->start);501 err = clock_gettime(CLOCK_MONOTONIC, &s->start);
484 if (err < 0)502 if (err < 0)
485 perror("recv start time: ");503 perror("recv start time: ");
@@ -488,7 +506,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, · 2 unmodified lines
488 timeout.tv_sec = 0;506 timeout.tv_sec = 0;
489 timeout.tv_usec = 300000;507 timeout.tv_usec = 300000;
490 } else {508 } else {
491 timeout.tv_sec = 1;509 timeout.tv_sec = 3;
492 timeout.tv_usec = 0;510 timeout.tv_usec = 0;
493 }511 }
494 512
@@ -503,7 +521,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt, · 8 unmodified lines
503 goto out_errno;521 goto out_errno;
504 } else if (!slct) {522 } else if (!slct) {
505 if (opt->verbose)523 if (opt->verbose)
506 fprintf(stderr, "unexpected timeout\n");524 fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total);
507 errno = -EIO;525 errno = -EIO;
508 clock_gettime(CLOCK_MONOTONIC, &s->end);526 clock_gettime(CLOCK_MONOTONIC, &s->end);
509 goto out_errno;527 goto out_errno;
@@ -619,7 +637,7 @@ static int sendmsg_test(struct sockmap_options *opt) · 109 unmodified lines
619 iov_count = 1;637 iov_count = 1;
620 err = msg_loop(rx_fd, iov_count, iov_buf,638 err = msg_loop(rx_fd, iov_count, iov_buf,
621 cnt, &s, false, opt);639 cnt, &s, false, opt);
622 if (err && opt->verbose)640 if (opt->verbose)
623 fprintf(stderr,641 fprintf(stderr,
624 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",642 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
625 iov_count, iov_buf, cnt, err);643 iov_count, iov_buf, cnt, err);
@@ -931,6 +949,39 @@ run: · 305 unmodified lines
931 }949 }
932 }950 }
933 951
952 if (txmsg_start_pop) {
953 i = 4;
954 err = bpf_map_update_elem(map_fd[5],
955 &i, &txmsg_start_pop, BPF_ANY);
956 if (err) {
957 fprintf(stderr,
958 "ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop): %d (%s)\n",
959 txmsg_start_pop, i, err, strerror(errno));
960 goto out;
961 }
962 } else {
963 i = 4;
964 bpf_map_update_elem(map_fd[5],
965 &i, &txmsg_start_pop, BPF_ANY);
966 }
967
968 if (txmsg_pop) {
969 i = 5;
970 err = bpf_map_update_elem(map_fd[5],
971 &i, &txmsg_pop, BPF_ANY);
972 if (err) {
973 fprintf(stderr,
974 "ERROR: bpf_map_update_elem %i@%i (txmsg_pop): %d (%s)\n",
975 txmsg_pop, i, err, strerror(errno));
976 goto out;
977 }
978 } else {
979 i = 5;
980 bpf_map_update_elem(map_fd[5],
981 &i, &txmsg_pop, BPF_ANY);
982
983 }
984
934 if (txmsg_ingress) {985 if (txmsg_ingress) {
935 int in = BPF_F_INGRESS;986 int in = BPF_F_INGRESS;
936 987
@@ -1082,6 +1133,11 @@ static void test_options(char *options) · 145 unmodified lines
1082 snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);1133 snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
1083 strncat(options, tstr, OPTSTRING);1134 strncat(options, tstr, OPTSTRING);
1084 }1135 }
1136 if (txmsg_start_pop) {
1137 snprintf(tstr, OPTSTRING, "pop (%d,%d),",
1138 txmsg_start_pop, txmsg_start_pop + txmsg_pop);
1139 strncat(options, tstr, OPTSTRING);
1140 }
1085 if (txmsg_ingress)1141 if (txmsg_ingress)
1086 strncat(options, "ingress,", OPTSTRING);1142 strncat(options, "ingress,", OPTSTRING);
1087 if (txmsg_skb)1143 if (txmsg_skb)
@@ -1264,6 +1320,7 @@ static int test_mixed(int cgrp) · 176 unmodified lines
1264 txmsg_apply = txmsg_cork = 0;1320 txmsg_apply = txmsg_cork = 0;
1265 txmsg_start = txmsg_end = 0;1321 txmsg_start = txmsg_end = 0;
1266 txmsg_start_push = txmsg_end_push = 0;1322 txmsg_start_push = txmsg_end_push = 0;
1323 txmsg_start_pop = txmsg_pop = 0;
1267 1324
1268 /* Test small and large iov_count values with pass/redir/apply/cork */1325 /* Test small and large iov_count values with pass/redir/apply/cork */
1269 txmsg_pass = 1;1326 txmsg_pass = 1;
@@ -1383,6 +1440,19 @@ static int test_start_end(int cgrp) · 113 unmodified lines
1383 txmsg_end = 2;1440 txmsg_end = 2;
1384 txmsg_start_push = 1;1441 txmsg_start_push = 1;
1385 txmsg_end_push = 2;1442 txmsg_end_push = 2;
1443 txmsg_start_pop = 1;
1444 txmsg_pop = 1;
1445 err = test_txmsg(cgrp);
1446 if (err)
1447 goto out;
1448
1449 /* Cut a byte of pushed data but leave reamining in place */
1450 txmsg_start = 1;
1451 txmsg_end = 2;
1452 txmsg_start_push = 1;
1453 txmsg_end_push = 3;
1454 txmsg_start_pop = 1;
1455 txmsg_pop = 1;
1386 err = test_txmsg(cgrp);1456 err = test_txmsg(cgrp);
1387 if (err)1457 if (err)
1388 goto out;1458 goto out;
@@ -1393,6 +1463,9 @@ static int test_start_end(int cgrp) · 4 unmodified lines
1393 opt.iov_length = 100;1463 opt.iov_length = 100;
1394 txmsg_cork = 1600;1464 txmsg_cork = 1600;
1395 1465
1466 txmsg_start_pop = 0;
1467 txmsg_pop = 0;
1468
1396 for (i = 99; i <= 1600; i += 500) {1469 for (i = 99; i <= 1600; i += 500) {
1397 txmsg_start = 0;1470 txmsg_start = 0;
1398 txmsg_end = i;1471 txmsg_end = i;
@@ -1403,6 +1476,17 @@ static int test_start_end(int cgrp) · 4 unmodified lines
1403 goto out;1476 goto out;
1404 }1477 }
1405 1478
1479 /* Test pop data in middle of cork */
1480 for (i = 99; i <= 1600; i += 500) {
1481 txmsg_start_pop = 10;
1482 txmsg_pop = i;
1483 err = test_exec(cgrp, &opt);
1484 if (err)
1485 goto out;
1486 }
1487 txmsg_start_pop = 0;
1488 txmsg_pop = 0;
1489
1406 /* Test start/end with cork but pull data in middle */1490 /* Test start/end with cork but pull data in middle */
1407 for (i = 199; i <= 1600; i += 500) {1491 for (i = 199; i <= 1600; i += 500) {
1408 txmsg_start = 100;1492 txmsg_start = 100;
@@ -1423,6 +1507,15 @@ static int test_start_end(int cgrp) · 14 unmodified lines
1423 if (err)1507 if (err)
1424 goto out;1508 goto out;
1425 1509
1510 /* Test pop with cork pulling last sg entry */
1511 txmsg_start_pop = 1500;
1512 txmsg_pop = 1600;
1513 err = test_exec(cgrp, &opt);
1514 if (err)
1515 goto out;
1516 txmsg_start_pop = 0;
1517 txmsg_pop = 0;
1518
1426 /* Test start/end pull of single byte in last page */1519 /* Test start/end pull of single byte in last page */
1427 txmsg_start = 1111;1520 txmsg_start = 1111;
1428 txmsg_end = 1112;1521 txmsg_end = 1112;
@@ -1432,6 +1525,13 @@ static int test_start_end(int cgrp) · 3 unmodified lines
1432 if (err)1525 if (err)
1433 goto out;1526 goto out;
1434 1527
1528 /* Test pop of single byte in last page */
1529 txmsg_start_pop = 1111;
1530 txmsg_pop = 1112;
1531 err = test_exec(cgrp, &opt);
1532 if (err)
1533 goto out;
1534
1435 /* Test start/end with end < start */1535 /* Test start/end with end < start */
1436 txmsg_start = 1111;1536 txmsg_start = 1111;
1437 txmsg_end = 0;1537 txmsg_end = 0;
@@ -1456,7 +1556,20 @@ static int test_start_end(int cgrp) · 18 unmodified lines
1456 txmsg_start_push = 1601;1556 txmsg_start_push = 1601;
1457 txmsg_end_push = 1600;1557 txmsg_end_push = 1600;
1458 err = test_exec(cgrp, &opt);1558 err = test_exec(cgrp, &opt);
1559 if (err)
1560 goto out;
1561
1562 /* Test pop with start > data */
1563 txmsg_start_pop = 1601;
1564 txmsg_pop = 1;
1565 err = test_exec(cgrp, &opt);
1566 if (err)
1567 goto out;
1459 1568
1569 /* Test pop with pop range > data */
1570 txmsg_start_pop = 1599;
1571 txmsg_pop = 10;
1572 err = test_exec(cgrp, &opt);
1460out:1573out:
1461 txmsg_start = 0;1574 txmsg_start = 0;
1462 txmsg_end = 0;1575 txmsg_end = 0;
@@ -1641,6 +1754,12 @@ int main(int argc, char **argv) · 178 unmodified lines
1641 case 'q':1754 case 'q':
1642 txmsg_end_push = atoi(optarg);1755 txmsg_end_push = atoi(optarg);
1643 break;1756 break;
1757 case 'w':
1758 txmsg_start_pop = atoi(optarg);
1759 break;
1760 case 'x':
1761 txmsg_pop = atoi(optarg);
1762 break;
1644 case 'a':1763 case 'a':
1645 txmsg_apply = atoi(optarg);1764 txmsg_apply = atoi(optarg);
1646 break;1765 break;
tools/testing/selftests/bpf/test_sockmap_kern.h+57−13
@@ -74,7 +74,7 @@ struct bpf_map_def SEC("maps") sock_bytes = { · 73 unmodified lines
74 .type = BPF_MAP_TYPE_ARRAY,74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int),75 .key_size = sizeof(int),
76 .value_size = sizeof(int),76 .value_size = sizeof(int),
77 .max_entries = 477 .max_entries = 6
78};78};
79 79
80struct bpf_map_def SEC("maps") sock_redir_flags = {80struct bpf_map_def SEC("maps") sock_redir_flags = {
@@ -181,8 +181,8 @@ int bpf_sockmap(struct bpf_sock_ops *skops) · 100 unmodified lines
181SEC("sk_msg1")181SEC("sk_msg1")
182int bpf_prog4(struct sk_msg_md *msg)182int bpf_prog4(struct sk_msg_md *msg)
183{183{
184 int *bytes, zero = 0, one = 1, two = 2, three = 3;184 int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
185 int *start, *end, *start_push, *end_push;185 int *start, *end, *start_push, *end_push, *start_pop, *pop;
186 186
187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
188 if (bytes)188 if (bytes)
@@ -198,15 +198,19 @@ int bpf_prog4(struct sk_msg_md *msg) · 9 unmodified lines
198 end_push = bpf_map_lookup_elem(&sock_bytes, &three);198 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
199 if (start_push && end_push)199 if (start_push && end_push)
200 bpf_msg_push_data(msg, *start_push, *end_push, 0);200 bpf_msg_push_data(msg, *start_push, *end_push, 0);
201 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
202 pop = bpf_map_lookup_elem(&sock_bytes, &five);
203 if (start_pop && pop)
204 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
201 return SK_PASS;205 return SK_PASS;
202}206}
203 207
204SEC("sk_msg2")208SEC("sk_msg2")
205int bpf_prog5(struct sk_msg_md *msg)209int bpf_prog5(struct sk_msg_md *msg)
206{210{
207 int zero = 0, one = 1, two = 2, three = 3;211 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
208 int *start, *end, *start_push, *end_push;212 int *start, *end, *start_push, *end_push, *start_pop, *pop;
209 int *bytes, len1, len2 = 0, len3;213 int *bytes, len1, len2 = 0, len3, len4;
210 int err1 = -1, err2 = -1;214 int err1 = -1, err2 = -1;
211 215
212 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);216 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
@@ -247,6 +251,20 @@ int bpf_prog5(struct sk_msg_md *msg) · 34 unmodified lines
247 bpf_printk("sk_msg2: length push_update %i->%i\n",251 bpf_printk("sk_msg2: length push_update %i->%i\n",
248 len2 ? len2 : len1, len3);252 len2 ? len2 : len1, len3);
249 }253 }
254 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
255 pop = bpf_map_lookup_elem(&sock_bytes, &five);
256 if (start_pop && pop) {
257 int err;
258
259 bpf_printk("sk_msg2: pop(%i@%i)\n",
260 start_pop, pop);
261 err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
262 if (err)
263 bpf_printk("sk_msg2: pop_data err %i\n", err);
264 len4 = (__u64)msg->data_end - (__u64)msg->data;
265 bpf_printk("sk_msg2: length pop_data %i->%i\n",
266 len1 ? len1 : 0, len4);
267 }
250 268
251 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",269 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
252 len1, err1, err2);270 len1, err1, err2);
@@ -256,8 +274,8 @@ int bpf_prog5(struct sk_msg_md *msg) · 3 unmodified lines
256SEC("sk_msg3")274SEC("sk_msg3")
257int bpf_prog6(struct sk_msg_md *msg)275int bpf_prog6(struct sk_msg_md *msg)
258{276{
259 int *bytes, *start, *end, *start_push, *end_push, *f;277 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
260 int zero = 0, one = 1, two = 2, three = 3, key = 0;278 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
261 __u64 flags = 0;279 __u64 flags = 0;
262 280
263 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);281 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
@@ -277,6 +295,11 @@ int bpf_prog6(struct sk_msg_md *msg) · 13 unmodified lines
277 if (start_push && end_push)295 if (start_push && end_push)
278 bpf_msg_push_data(msg, *start_push, *end_push, 0);296 bpf_msg_push_data(msg, *start_push, *end_push, 0);
279 297
298 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
299 pop = bpf_map_lookup_elem(&sock_bytes, &five);
300 if (start_pop && pop)
301 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
302
280 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);303 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
281 if (f && *f) {304 if (f && *f) {
282 key = 2;305 key = 2;
@@ -292,8 +315,9 @@ int bpf_prog6(struct sk_msg_md *msg) · 9 unmodified lines
292SEC("sk_msg4")315SEC("sk_msg4")
293int bpf_prog7(struct sk_msg_md *msg)316int bpf_prog7(struct sk_msg_md *msg)
294{317{
295 int zero = 0, one = 1, two = 2, three = 3, len1, len2 = 0, len3;318 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
296 int *bytes, *start, *end, *start_push, *end_push, *f;319 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
320 int len1, len2 = 0, len3, len4;
297 int err1 = 0, err2 = 0, key = 0;321 int err1 = 0, err2 = 0, key = 0;
298 __u64 flags = 0;322 __u64 flags = 0;
299 323
@@ -335,6 +359,22 @@ int bpf_prog7(struct sk_msg_md *msg) · 35 unmodified lines
335 len2 ? len2 : len1, len3);359 len2 ? len2 : len1, len3);
336 }360 }
337 361
362 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
363 pop = bpf_map_lookup_elem(&sock_bytes, &five);
364 if (start_pop && pop) {
365 int err;
366
367 bpf_printk("sk_msg4: pop(%i@%i)\n",
368 start_pop, pop);
369 err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
370 if (err)
371 bpf_printk("sk_msg4: pop_data err %i\n", err);
372 len4 = (__u64)msg->data_end - (__u64)msg->data;
373 bpf_printk("sk_msg4: length pop_data %i->%i\n",
374 len1 ? len1 : 0, len4);
375 }
376
377
338 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);378 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
339 if (f && *f) {379 if (f && *f) {
340 key = 2;380 key = 2;
@@ -389,8 +429,8 @@ int bpf_prog9(struct sk_msg_md *msg) · 48 unmodified lines
389SEC("sk_msg7")429SEC("sk_msg7")
390int bpf_prog10(struct sk_msg_md *msg)430int bpf_prog10(struct sk_msg_md *msg)
391{431{
392 int *bytes, *start, *end, *start_push, *end_push;432 int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
393 int zero = 0, one = 1, two = 2, three = 3;433 int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
394 434
395 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);435 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
396 if (bytes)436 if (bytes)
@@ -406,7 +446,11 @@ int bpf_prog10(struct sk_msg_md *msg) · 9 unmodified lines
406 end_push = bpf_map_lookup_elem(&sock_bytes, &three);446 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
407 if (start_push && end_push)447 if (start_push && end_push)
408 bpf_msg_push_data(msg, *start_push, *end_push, 0);448 bpf_msg_push_data(msg, *start_push, *end_push, 0);
409 449 start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
450 pop = bpf_map_lookup_elem(&sock_bytes, &five);
451 if (start_pop && pop)
452 bpf_msg_pop_data(msg, *start_pop, *pop, 0);
453 bpf_printk("return sk drop\n");
410 return SK_DROP;454 return SK_DROP;
411}455}
412 456