Commit 3b7a8ec2 authored by Maciej Fijalkowski's avatar Maciej Fijalkowski Committed by Daniel Borkmann
Browse files

samples/bpf: Check the prog id before exiting



Check the program id within the signal handler on polling xdp samples
that were previously converted to libbpf usage. Avoid the situation of
unloading the program that was not attached by sample that is exiting.
Handle also the case where bpf_get_link_xdp_id didn't exit with an error
but the xdp program was not found on an interface.

Reported-by: default avatarMichal Papaj <michal.papaj@intel.com>
Reported-by: default avatarJakub Spizewski <jakub.spizewski@intel.com>
Signed-off-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 50db9f07
Loading
Loading
Loading
Loading
+23 −1
Original line number Original line Diff line number Diff line
@@ -23,10 +23,22 @@


static int ifindex;
static int ifindex;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 prog_id;


static void int_exit(int sig)
static void int_exit(int sig)
{
{
	__u32 curr_prog_id = 0;

	if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
		printf("bpf_get_link_xdp_id failed\n");
		exit(1);
	}
	if (prog_id == curr_prog_id)
		bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
		bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
	else if (!curr_prog_id)
		printf("couldn't find a prog id on a given interface\n");
	else
		printf("program on interface changed, not removing\n");
	exit(0);
	exit(0);
}
}


@@ -74,11 +86,14 @@ int main(int argc, char **argv)
	struct bpf_prog_load_attr prog_load_attr = {
	struct bpf_prog_load_attr prog_load_attr = {
		.prog_type	= BPF_PROG_TYPE_XDP,
		.prog_type	= BPF_PROG_TYPE_XDP,
	};
	};
	struct bpf_prog_info info = {};
	__u32 info_len = sizeof(info);
	const char *optstr = "FSN";
	const char *optstr = "FSN";
	int prog_fd, map_fd, opt;
	int prog_fd, map_fd, opt;
	struct bpf_object *obj;
	struct bpf_object *obj;
	struct bpf_map *map;
	struct bpf_map *map;
	char filename[256];
	char filename[256];
	int err;


	while ((opt = getopt(argc, argv, optstr)) != -1) {
	while ((opt = getopt(argc, argv, optstr)) != -1) {
		switch (opt) {
		switch (opt) {
@@ -139,6 +154,13 @@ int main(int argc, char **argv)
		return 1;
		return 1;
	}
	}


	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (err) {
		printf("can't get prog info - %s\n", strerror(errno));
		return err;
	}
	prog_id = info.id;

	poll_stats(map_fd, 2);
	poll_stats(map_fd, 2);


	return 0;
	return 0;
+26 −4
Original line number Original line Diff line number Diff line
@@ -25,11 +25,24 @@


static int ifindex = -1;
static int ifindex = -1;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 prog_id;


static void int_exit(int sig)
static void int_exit(int sig)
{
{
	if (ifindex > -1)
	__u32 curr_prog_id = 0;

	if (ifindex > -1) {
		if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
			printf("bpf_get_link_xdp_id failed\n");
			exit(1);
		}
		if (prog_id == curr_prog_id)
			bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
			bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
		else if (!curr_prog_id)
			printf("couldn't find a prog id on a given iface\n");
		else
			printf("program on interface changed, not removing\n");
	}
	exit(0);
	exit(0);
}
}


@@ -72,11 +85,14 @@ int main(int argc, char **argv)
	};
	};
	unsigned char opt_flags[256] = {};
	unsigned char opt_flags[256] = {};
	const char *optstr = "i:T:SNFh";
	const char *optstr = "i:T:SNFh";
	struct bpf_prog_info info = {};
	__u32 info_len = sizeof(info);
	unsigned int kill_after_s = 0;
	unsigned int kill_after_s = 0;
	int i, prog_fd, map_fd, opt;
	int i, prog_fd, map_fd, opt;
	struct bpf_object *obj;
	struct bpf_object *obj;
	struct bpf_map *map;
	struct bpf_map *map;
	char filename[256];
	char filename[256];
	int err;


	for (i = 0; i < strlen(optstr); i++)
	for (i = 0; i < strlen(optstr); i++)
		if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
		if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
@@ -146,9 +162,15 @@ int main(int argc, char **argv)
		return 1;
		return 1;
	}
	}


	poll_stats(map_fd, kill_after_s);
	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (err) {
		printf("can't get prog info - %s\n", strerror(errno));
		return 1;
	}
	prog_id = info.id;


	bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
	poll_stats(map_fd, kill_after_s);
	int_exit(0);


	return 0;
	return 0;
}
}
+29 −6
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ static const char *__doc__ =
static int ifindex = -1;
static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char ifname_buf[IF_NAMESIZE];
static char *ifname;
static char *ifname;
static __u32 prog_id;


static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int cpu_map_fd;
static int cpu_map_fd;
@@ -68,11 +69,24 @@ static const struct option long_options[] = {


static void int_exit(int sig)
static void int_exit(int sig)
{
{
	__u32 curr_prog_id = 0;

	if (ifindex > -1) {
		if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
			printf("bpf_get_link_xdp_id failed\n");
			exit(EXIT_FAIL);
		}
		if (prog_id == curr_prog_id) {
			fprintf(stderr,
			fprintf(stderr,
				"Interrupted: Removing XDP program on ifindex:%d device:%s\n",
				"Interrupted: Removing XDP program on ifindex:%d device:%s\n",
				ifindex, ifname);
				ifindex, ifname);
	if (ifindex > -1)
			bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
			bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
		} else if (!curr_prog_id) {
			printf("couldn't find a prog id on a given iface\n");
		} else {
			printf("program on interface changed, not removing\n");
		}
	}
	exit(EXIT_OK);
	exit(EXIT_OK);
}
}


@@ -608,6 +622,8 @@ int main(int argc, char **argv)
	struct bpf_prog_load_attr prog_load_attr = {
	struct bpf_prog_load_attr prog_load_attr = {
		.prog_type	= BPF_PROG_TYPE_UNSPEC,
		.prog_type	= BPF_PROG_TYPE_UNSPEC,
	};
	};
	struct bpf_prog_info info = {};
	__u32 info_len = sizeof(info);
	bool use_separators = true;
	bool use_separators = true;
	bool stress_mode = false;
	bool stress_mode = false;
	struct bpf_program *prog;
	struct bpf_program *prog;
@@ -617,9 +633,9 @@ int main(int argc, char **argv)
	int longindex = 0;
	int longindex = 0;
	int interval = 2;
	int interval = 2;
	int add_cpu = -1;
	int add_cpu = -1;
	int opt, err;
	int prog_fd;
	int prog_fd;
	__u32 qsize;
	__u32 qsize;
	int opt;


	/* Notice: choosing he queue size is very important with the
	/* Notice: choosing he queue size is very important with the
	 * ixgbe driver, because it's driver page recycling trick is
	 * ixgbe driver, because it's driver page recycling trick is
@@ -746,6 +762,13 @@ int main(int argc, char **argv)
		return EXIT_FAIL_XDP;
		return EXIT_FAIL_XDP;
	}
	}


	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (err) {
		printf("can't get prog info - %s\n", strerror(errno));
		return err;
	}
	prog_id = info.id;

	stats_poll(interval, use_separators, prog_name, stress_mode);
	stats_poll(interval, use_separators, prog_name, stress_mode);
	return EXIT_OK;
	return EXIT_OK;
}
}
+46 −3
Original line number Original line Diff line number Diff line
@@ -29,15 +29,41 @@
static int ifindex_in;
static int ifindex_in;
static int ifindex_out;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
static bool ifindex_out_xdp_dummy_attached = true;
static __u32 prog_id;
static __u32 dummy_prog_id;


static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static int rxcnt_map_fd;


static void int_exit(int sig)
static void int_exit(int sig)
{
{
	__u32 curr_prog_id = 0;

	if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
		printf("bpf_get_link_xdp_id failed\n");
		exit(1);
	}
	if (prog_id == curr_prog_id)
		bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
		bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
	if (ifindex_out_xdp_dummy_attached)
	else if (!curr_prog_id)
		printf("couldn't find a prog id on iface IN\n");
	else
		printf("program on iface IN changed, not removing\n");

	if (ifindex_out_xdp_dummy_attached) {
		curr_prog_id = 0;
		if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
					xdp_flags)) {
			printf("bpf_get_link_xdp_id failed\n");
			exit(1);
		}
		if (prog_id == curr_prog_id)
			bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
			bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
		else if (!curr_prog_id)
			printf("couldn't find a prog id on iface OUT\n");
		else
			printf("program on iface OUT changed, not removing\n");
	}
	exit(0);
	exit(0);
}
}


@@ -82,6 +108,8 @@ int main(int argc, char **argv)
		.prog_type	= BPF_PROG_TYPE_XDP,
		.prog_type	= BPF_PROG_TYPE_XDP,
	};
	};
	struct bpf_program *prog, *dummy_prog;
	struct bpf_program *prog, *dummy_prog;
	struct bpf_prog_info info = {};
	__u32 info_len = sizeof(info);
	int prog_fd, dummy_prog_fd;
	int prog_fd, dummy_prog_fd;
	const char *optstr = "FSN";
	const char *optstr = "FSN";
	struct bpf_object *obj;
	struct bpf_object *obj;
@@ -153,6 +181,13 @@ int main(int argc, char **argv)
		return 1;
		return 1;
	}
	}


	ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (ret) {
		printf("can't get prog info - %s\n", strerror(errno));
		return ret;
	}
	prog_id = info.id;

	/* Loading dummy XDP prog on out-device */
	/* Loading dummy XDP prog on out-device */
	if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
	if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
			    (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
			    (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
@@ -160,6 +195,14 @@ int main(int argc, char **argv)
		ifindex_out_xdp_dummy_attached = false;
		ifindex_out_xdp_dummy_attached = false;
	}
	}


	memset(&info, 0, sizeof(info));
	ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len);
	if (ret) {
		printf("can't get prog info - %s\n", strerror(errno));
		return ret;
	}
	dummy_prog_id = info.id;

	signal(SIGINT, int_exit);
	signal(SIGINT, int_exit);
	signal(SIGTERM, int_exit);
	signal(SIGTERM, int_exit);


+46 −3
Original line number Original line Diff line number Diff line
@@ -29,15 +29,41 @@
static int ifindex_in;
static int ifindex_in;
static int ifindex_out;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
static bool ifindex_out_xdp_dummy_attached = true;
static __u32 prog_id;
static __u32 dummy_prog_id;


static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static int rxcnt_map_fd;


static void int_exit(int sig)
static void int_exit(int sig)
{
{
	__u32 curr_prog_id = 0;

	if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
		printf("bpf_get_link_xdp_id failed\n");
		exit(1);
	}
	if (prog_id == curr_prog_id)
		bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
		bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
	if (ifindex_out_xdp_dummy_attached)
	else if (!curr_prog_id)
		printf("couldn't find a prog id on iface IN\n");
	else
		printf("program on iface IN changed, not removing\n");

	if (ifindex_out_xdp_dummy_attached) {
		curr_prog_id = 0;
		if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
					xdp_flags)) {
			printf("bpf_get_link_xdp_id failed\n");
			exit(1);
		}
		if (prog_id == curr_prog_id)
			bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
			bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
		else if (!curr_prog_id)
			printf("couldn't find a prog id on iface OUT\n");
		else
			printf("program on iface OUT changed, not removing\n");
	}
	exit(0);
	exit(0);
}
}


@@ -84,6 +110,8 @@ int main(int argc, char **argv)
	};
	};
	struct bpf_program *prog, *dummy_prog;
	struct bpf_program *prog, *dummy_prog;
	int prog_fd, tx_port_map_fd, opt;
	int prog_fd, tx_port_map_fd, opt;
	struct bpf_prog_info info = {};
	__u32 info_len = sizeof(info);
	const char *optstr = "FSN";
	const char *optstr = "FSN";
	struct bpf_object *obj;
	struct bpf_object *obj;
	char filename[256];
	char filename[256];
@@ -154,6 +182,13 @@ int main(int argc, char **argv)
		return 1;
		return 1;
	}
	}


	ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (ret) {
		printf("can't get prog info - %s\n", strerror(errno));
		return ret;
	}
	prog_id = info.id;

	/* Loading dummy XDP prog on out-device */
	/* Loading dummy XDP prog on out-device */
	if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
	if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
			    (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
			    (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
@@ -161,6 +196,14 @@ int main(int argc, char **argv)
		ifindex_out_xdp_dummy_attached = false;
		ifindex_out_xdp_dummy_attached = false;
	}
	}


	memset(&info, 0, sizeof(info));
	ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (ret) {
		printf("can't get prog info - %s\n", strerror(errno));
		return ret;
	}
	dummy_prog_id = info.id;

	signal(SIGINT, int_exit);
	signal(SIGINT, int_exit);
	signal(SIGTERM, int_exit);
	signal(SIGTERM, int_exit);


Loading