162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* eBPF example program:
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * - Loads eBPF program
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *   The eBPF program loads a filter from file and attaches the
762306a36Sopenharmony_ci *   program to a cgroup using BPF_PROG_ATTACH
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define _GNU_SOURCE
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <stdio.h>
1362306a36Sopenharmony_ci#include <stdlib.h>
1462306a36Sopenharmony_ci#include <stddef.h>
1562306a36Sopenharmony_ci#include <string.h>
1662306a36Sopenharmony_ci#include <unistd.h>
1762306a36Sopenharmony_ci#include <assert.h>
1862306a36Sopenharmony_ci#include <errno.h>
1962306a36Sopenharmony_ci#include <fcntl.h>
2062306a36Sopenharmony_ci#include <net/if.h>
2162306a36Sopenharmony_ci#include <linux/bpf.h>
2262306a36Sopenharmony_ci#include <bpf/bpf.h>
2362306a36Sopenharmony_ci#include <bpf/libbpf.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include "bpf_insn.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic int usage(const char *argv0)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	printf("Usage: %s cg-path filter-path [filter-id]\n", argv0);
3062306a36Sopenharmony_ci	return EXIT_FAILURE;
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciint main(int argc, char **argv)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	int cg_fd, err, ret = EXIT_FAILURE, filter_id = 0, prog_cnt = 0;
3662306a36Sopenharmony_ci	const char *link_pin_path = "/sys/fs/bpf/test_cgrp2_sock2";
3762306a36Sopenharmony_ci	struct bpf_link *link = NULL;
3862306a36Sopenharmony_ci	struct bpf_program *progs[2];
3962306a36Sopenharmony_ci	struct bpf_program *prog;
4062306a36Sopenharmony_ci	struct bpf_object *obj;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (argc < 3)
4362306a36Sopenharmony_ci		return usage(argv[0]);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if (argc > 3)
4662306a36Sopenharmony_ci		filter_id = atoi(argv[3]);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
4962306a36Sopenharmony_ci	if (cg_fd < 0) {
5062306a36Sopenharmony_ci		printf("Failed to open cgroup path: '%s'\n", strerror(errno));
5162306a36Sopenharmony_ci		return ret;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	obj = bpf_object__open_file(argv[2], NULL);
5562306a36Sopenharmony_ci	if (libbpf_get_error(obj)) {
5662306a36Sopenharmony_ci		printf("ERROR: opening BPF object file failed\n");
5762306a36Sopenharmony_ci		return ret;
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	bpf_object__for_each_program(prog, obj) {
6162306a36Sopenharmony_ci		progs[prog_cnt] = prog;
6262306a36Sopenharmony_ci		prog_cnt++;
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (filter_id >= prog_cnt) {
6662306a36Sopenharmony_ci		printf("Invalid program id; program not found in file\n");
6762306a36Sopenharmony_ci		goto cleanup;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* load BPF program */
7162306a36Sopenharmony_ci	if (bpf_object__load(obj)) {
7262306a36Sopenharmony_ci		printf("ERROR: loading BPF object file failed\n");
7362306a36Sopenharmony_ci		goto cleanup;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	link = bpf_program__attach_cgroup(progs[filter_id], cg_fd);
7762306a36Sopenharmony_ci	if (libbpf_get_error(link)) {
7862306a36Sopenharmony_ci		printf("ERROR: bpf_program__attach failed\n");
7962306a36Sopenharmony_ci		link = NULL;
8062306a36Sopenharmony_ci		goto cleanup;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	err = bpf_link__pin(link, link_pin_path);
8462306a36Sopenharmony_ci	if (err < 0) {
8562306a36Sopenharmony_ci		printf("ERROR: bpf_link__pin failed: %d\n", err);
8662306a36Sopenharmony_ci		goto cleanup;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	ret = EXIT_SUCCESS;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cicleanup:
9262306a36Sopenharmony_ci	bpf_link__destroy(link);
9362306a36Sopenharmony_ci	bpf_object__close(obj);
9462306a36Sopenharmony_ci	return ret;
9562306a36Sopenharmony_ci}
96