static int set_cpumap_prog()

in bpf/xdp_redirect_cpu_user.c [176:304]


static int set_cpumap_prog(struct xdp_redirect_cpu *skel,
			   const char *redir_interface, const char *redir_map,
			   const char *mprog_filename, const char *mprog_name)
{
	if (mprog_filename) {
		struct bpf_program *prog;
		struct bpf_object *obj;
		int ret;

		if (!mprog_name) {
			fprintf(stderr, "BPF program not specified for file %s\n",
				mprog_filename);
			goto end;
		}
		if ((redir_interface && !redir_map) || (!redir_interface && redir_map)) {
			fprintf(stderr, "--redirect-%s specified but --redirect-%s not specified\n",
				redir_interface ? "device" : "map", redir_interface ? "map" : "device");
			goto end;
		}

		/* Custom BPF program */
		obj = bpf_object__open_file(mprog_filename, NULL);
		if (!obj) {
			ret = -errno;
			fprintf(stderr, "Failed to bpf_prog_load_xattr: %s\n",
				strerror(errno));
			return ret;
		}

		ret = bpf_object__load(obj);
		if (ret < 0) {
			ret = -errno;
			fprintf(stderr, "Failed to bpf_object__load: %s\n",
				strerror(errno));
			return ret;
		}

		if (redir_map) {
			int err, redir_map_fd, ifindex_out, key = 0;

			redir_map_fd = bpf_object__find_map_fd_by_name(obj, redir_map);
			if (redir_map_fd < 0) {
				fprintf(stderr, "Failed to bpf_object__find_map_fd_by_name: %s\n",
					strerror(errno));
				return redir_map_fd;
			}

			ifindex_out = if_nametoindex(redir_interface);
			if (!ifindex_out)
				ifindex_out = strtoul(redir_interface, NULL, 0);
			if (!ifindex_out) {
				fprintf(stderr, "Bad interface name or index\n");
				return -EINVAL;
			}

			err = bpf_map_update_elem(redir_map_fd, &key, &ifindex_out, 0);
			if (err < 0)
				return err;
		}

		prog = bpf_object__find_program_by_name(obj, mprog_name);
		if (!prog) {
			ret = -errno;
			fprintf(stderr, "Failed to bpf_object__find_program_by_name: %s\n",
				strerror(errno));
			return ret;
		}

		return bpf_program__fd(prog);
	} else {
		if (mprog_name) {
			if (redir_interface || redir_map) {
				fprintf(stderr, "Need to specify --mprog-filename/-f\n");
				goto end;
			}
			if (!strcmp(mprog_name, "pass") || !strcmp(mprog_name, "drop")) {
				/* Use built-in pass/drop programs */
				return *mprog_name == 'p' ? bpf_program__fd(skel->progs.xdp_redirect_cpu_pass)
					: bpf_program__fd(skel->progs.xdp_redirect_cpu_drop);
			} else {
				fprintf(stderr, "Unknown name \"%s\" for built-in BPF program\n",
					mprog_name);
				goto end;
			}
		} else {
			if (redir_map) {
				fprintf(stderr, "Need to specify --mprog-filename, --mprog-name and"
					" --redirect-device with --redirect-map\n");
				goto end;
			}
			if (redir_interface) {
				/* Use built-in devmap redirect */
				struct bpf_devmap_val val = {};
				int ifindex_out, err;
				__u32 key = 0;

				if (!redir_interface)
					return 0;

				ifindex_out = if_nametoindex(redir_interface);
				if (!ifindex_out)
					ifindex_out = strtoul(redir_interface, NULL, 0);
				if (!ifindex_out) {
					fprintf(stderr, "Bad interface name or index\n");
					return -EINVAL;
				}

				if (get_mac_addr(ifindex_out, skel->bss->tx_mac_addr) < 0) {
					printf("Get interface %d mac failed\n", ifindex_out);
					return -EINVAL;
				}

				val.ifindex = ifindex_out;
				val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_redirect_egress_prog);
				err = bpf_map_update_elem(bpf_map__fd(skel->maps.tx_port), &key, &val, 0);
				if (err < 0)
					return -errno;

				return bpf_program__fd(skel->progs.xdp_redirect_cpu_devmap);
			}
		}
	}

	/* Disabled */
	return 0;
end:
	fprintf(stderr, "Invalid options for CPUMAP BPF program\n");
	return -EINVAL;
}