tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c
Extension
.c
Size
8722 bytes
Lines
279
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err && errno == ENOSPC) {
			/* Fetch again with higher batch size */
			total_fetched = 0;
			step_size += batch_size;
			continue;
		}

		CHECK((err < 0 && (errno != ENOENT)),
		      "lookup with steps failed",
		      "error: %s\n", strerror(errno));

		/* Update the total fetched number */
		total_fetched += fetch_count;
		if (err)
			break;
	}

	CHECK((total_fetched != max_entries),
	      "Unable to fetch expected entries !",
	      "total_fetched(%d) and max_entries(%d) error: (%d):%s\n",
	      total_fetched, max_entries, errno, strerror(errno));

	/* validate the fetched entries */
	validate_fetch_results(outer_map_fd, fetched_keys,
			       fetched_values, total_fetched);
	printf("batch_op(%s) is successful with batch_size(%d)\n",
	       delete_entries ? "LOOKUP_AND_DELETE" : "LOOKUP", batch_size);

	free(fetched_keys);
	free(fetched_values);
}

static void _map_in_map_batch_ops(enum bpf_map_type outer_map_type,
				  enum bpf_map_type inner_map_type,
				  bool has_holes)
{
	__u32 max_entries = OUTER_MAP_ENTRIES - !!has_holes;
	__u32 *outer_map_keys, *inner_map_fds;
	LIBBPF_OPTS(bpf_map_batch_opts, opts);
	__u32 value_size = sizeof(__u32);
	int batch_size[2] = {5, 10};
	__u32 map_index, op_index;
	int outer_map_fd, ret;

	outer_map_keys = calloc(OUTER_MAP_ENTRIES, value_size);
	inner_map_fds = calloc(OUTER_MAP_ENTRIES, value_size);
	CHECK((!outer_map_keys || !inner_map_fds),
	      "Memory allocation failed for outer_map_keys or inner_map_fds",
	      "error=%s\n", strerror(errno));

	create_inner_maps(inner_map_type, inner_map_fds);

	outer_map_fd = create_outer_map(outer_map_type, *inner_map_fds);
	/* create outer map keys */
	for (map_index = 0; map_index < max_entries; map_index++)
		outer_map_keys[map_index] =
			((outer_map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
			 ? 9 : 1000) - map_index;

	/* This condition is only meaningful for array of maps.
	 *
	 * max_entries == OUTER_MAP_ENTRIES - 1 if it is true. Say
	 * max_entries is short for n, then outer_map_keys looks like:
	 *
	 *   [n, n-1, ... 2, 1]
	 *
	 * We change it to
	 *
	 *   [n, n-1, ... 2, 0]
	 *
	 * So it will leave key 1 as a hole. It will serve to test the
	 * correctness when batch on an array: a "non-exist" key might be
	 * actually allocated and returned from key iteration.
	 */
	if (has_holes)
		outer_map_keys[max_entries - 1]--;

	/* batch operation - map_update */
	ret = bpf_map_update_batch(outer_map_fd, outer_map_keys,
				   inner_map_fds, &max_entries, &opts);
	CHECK(ret != 0,
	      "Failed to update the outer map batch ops",
	      "error=%s\n", strerror(errno));

	/* batch operation - map_lookup */
	for (op_index = 0; op_index < 2; ++op_index)
		fetch_and_validate(outer_map_fd, &opts,
				   batch_size[op_index], false,
				   has_holes);

Annotation

Implementation Notes