mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	| @@ -1,30 +0,0 @@ | |||||||
| include $(TOPDIR)/rules.mk |  | ||||||
|  |  | ||||||
| PKG_NAME:=ubpf |  | ||||||
| PKG_RELEASE:=1 |  | ||||||
|  |  | ||||||
| PKG_LICENSE:=GPL-2.0+ |  | ||||||
| PKG_LICENSE_FILES:= |  | ||||||
|  |  | ||||||
| include $(INCLUDE_DIR)/package.mk |  | ||||||
| include $(INCLUDE_DIR)/cmake.mk |  | ||||||
|  |  | ||||||
| define Package/ubpf |  | ||||||
|   SECTION:=net |  | ||||||
|   CATEGORY:=Network |  | ||||||
|   DEPENDS:=+libubox +libbpf +libnl-tiny |  | ||||||
|   TITLE:=eBPF loader |  | ||||||
| endef |  | ||||||
|  |  | ||||||
| TARGET_CFLAGS += \ |  | ||||||
| 	-I$(STAGING_DIR)/usr/include \ |  | ||||||
| 	-I$(STAGING_DIR)/usr/include/libnl-tiny |  | ||||||
|  |  | ||||||
| define Package/ubpf/install |  | ||||||
| 	$(INSTALL_DIR) $(1)/sbin |  | ||||||
| 	$(INSTALL_BIN) $(PKG_BUILD_DIR)/xdpload $(1)/sbin/ |  | ||||||
| 	$(INSTALL_BIN) $(PKG_BUILD_DIR)/xdplist $(1)/sbin/ |  | ||||||
| 	$(INSTALL_BIN) $(PKG_BUILD_DIR)/uxdp $(1)/sbin/ |  | ||||||
| endef |  | ||||||
|  |  | ||||||
| $(eval $(call BuildPackage,ubpf)) |  | ||||||
| @@ -1,25 +0,0 @@ | |||||||
| cmake_minimum_required(VERSION 2.6) |  | ||||||
|  |  | ||||||
| PROJECT(ustatus C) |  | ||||||
| INCLUDE(GNUInstallDirs) |  | ||||||
| ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations -D__KERNEL__) |  | ||||||
|  |  | ||||||
| SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") |  | ||||||
|  |  | ||||||
| ADD_EXECUTABLE(xdpload xdpload.c xdp.c map.c prog.c net.c) |  | ||||||
| TARGET_LINK_LIBRARIES(xdpload bpf nl-tiny) |  | ||||||
| INSTALL(TARGETS xdpload |  | ||||||
| 	RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| ADD_EXECUTABLE(xdplist xdplist.c prog.c net.c map.c) |  | ||||||
| TARGET_LINK_LIBRARIES(xdplist bpf nl-tiny) |  | ||||||
| INSTALL(TARGETS xdplist |  | ||||||
| 	RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| ADD_EXECUTABLE(uxdp uxdp.c prog.c net.c map.c) |  | ||||||
| TARGET_LINK_LIBRARIES(uxdp bpf nl-tiny) |  | ||||||
| INSTALL(TARGETS uxdp |  | ||||||
| 	RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} |  | ||||||
| ) |  | ||||||
| @@ -1,83 +0,0 @@ | |||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| void |  | ||||||
| map_find(struct xdp_map *lookup, __u32 map) |  | ||||||
| { |  | ||||||
| 	__u32 id = 0; |  | ||||||
| 	int err; |  | ||||||
|  |  | ||||||
| 	while (true) { |  | ||||||
| 		struct bpf_map_info info = {}; |  | ||||||
| 		__u32 len = sizeof(info); |  | ||||||
| 		int fd; |  | ||||||
|  |  | ||||||
| 		err = bpf_map_get_next_id(id, &id); |  | ||||||
| 		if (err) { |  | ||||||
| 			if (errno == ENOENT) |  | ||||||
| 				break; |  | ||||||
| 			fprintf(stderr, "bpf_map_get_next_id failed\n"); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (id != map) |  | ||||||
| 			continue; |  | ||||||
|  |  | ||||||
| 		fd = bpf_map_get_fd_by_id(id); |  | ||||||
| 		if (fd < 0) { |  | ||||||
| 			if (errno == ENOENT) |  | ||||||
| 				continue; |  | ||||||
| 			fprintf(stderr, "bpf_map_get_fd_by_id failed\n"); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		err = bpf_obj_get_info_by_fd(fd, &info, &len); |  | ||||||
| 		if (err) { |  | ||||||
| 			fprintf(stderr, "bpf_obj_get_info_by_fd failed\n"); |  | ||||||
| 			close(fd); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		if (!lookup) { |  | ||||||
| 			fprintf(stderr, "\t\t%u: %s\n", info.id, *info.name ? info.name : "(unknown)"); |  | ||||||
| 			goto next; |  | ||||||
| 		} |  | ||||||
| 		if (!*info.name) |  | ||||||
| 			goto next; |  | ||||||
| 		if (strcmp(lookup->map, info.name)) |  | ||||||
| 			goto next; |  | ||||||
| 		memcpy(&lookup->map_info, &info, sizeof(info)); |  | ||||||
| 		lookup->map_fd = fd; |  | ||||||
| 		lookup->map_id = id; |  | ||||||
| 		continue; |  | ||||||
| next: |  | ||||||
| 		close(fd); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| map_lookup(struct xdp_map *lookup) |  | ||||||
| { |  | ||||||
| 	net_find(lookup); |  | ||||||
| 	if (!lookup->map_fd) |  | ||||||
| 		return -1; |  | ||||||
| 	if (map_verify(&lookup->map_info, &lookup->map_want)) |  | ||||||
| 		return -1; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| map_verify(struct bpf_map_info *map, struct bpf_map_info *exp) |  | ||||||
| { |  | ||||||
| 	if (exp->key_size && exp->key_size != map->key_size) |  | ||||||
| 		return -1; |  | ||||||
| 	if (exp->value_size && exp->value_size != map->value_size) |  | ||||||
| 		return -1; |  | ||||||
| 	if (exp->max_entries && exp->max_entries != map->max_entries) |  | ||||||
| 		return -1; |  | ||||||
| 	if (exp->type && exp->type  != map->type) |  | ||||||
| 		return -1; |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1,69 +0,0 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
|  |  | ||||||
| #define _GNU_SOURCE |  | ||||||
|  |  | ||||||
| #include <linux/rtnetlink.h> |  | ||||||
|  |  | ||||||
| #include <unl.h> |  | ||||||
|  |  | ||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| static struct unl unl; |  | ||||||
|  |  | ||||||
| static int |  | ||||||
| getlink_recv(struct nl_msg *msg, void *arg) |  | ||||||
| { |  | ||||||
| 	struct xdp_map *lookup = (struct xdp_map *) arg; |  | ||||||
| 	struct ifinfomsg *ifi = nlmsg_data(msg->nm_nlh); |  | ||||||
| 	struct nlattr *tb[IFLA_MAX + 1] = {}; |  | ||||||
| 	struct nlattr *xdp[IFLA_XDP_MAX + 1] = {}; |  | ||||||
| 	unsigned char mode; |  | ||||||
| 	char *ifname; |  | ||||||
|  |  | ||||||
| 	if (!nlmsg_valid_hdr(msg->nm_nlh, sizeof(*ifi)) || ifi->ifi_family != AF_UNSPEC) |  | ||||||
| 		return NL_SKIP; |  | ||||||
|  |  | ||||||
| 	nlmsg_parse(msg->nm_nlh, sizeof(*ifi), tb, __IFLA_MAX - 1, NULL); |  | ||||||
| 	if (!tb[IFLA_IFNAME] || !tb[IFLA_XDP]) |  | ||||||
| 		return NL_SKIP; |  | ||||||
| 	ifname = nla_get_string(tb[IFLA_IFNAME]); |  | ||||||
| 	if (nla_parse_nested(xdp, IFLA_XDP_MAX, tb[IFLA_XDP], NULL)) |  | ||||||
| 		return NL_SKIP; |  | ||||||
|  |  | ||||||
| 	if (!xdp[IFLA_XDP_ATTACHED]) |  | ||||||
| 		return NL_SKIP; |  | ||||||
|  |  | ||||||
| 	mode = nla_get_u8(xdp[IFLA_XDP_ATTACHED]); |  | ||||||
| 	if (mode == XDP_ATTACHED_NONE) |  | ||||||
| 		return NL_SKIP; |  | ||||||
| 	switch(mode) { |  | ||||||
| 	case XDP_ATTACHED_MULTI: |  | ||||||
| 		fprintf(stderr, "%s:%s[%d]XDP_ATTACHED_MULTI not supported yet\n", __FILE__, __func__, __LINE__); |  | ||||||
| 		break; |  | ||||||
| 	case XDP_ATTACHED_DRV: |  | ||||||
| 	case XDP_ATTACHED_SKB: |  | ||||||
| 	case XDP_ATTACHED_HW: |  | ||||||
| 		if (!lookup) |  | ||||||
| 			fprintf(stderr, "%s\n", ifname); |  | ||||||
| 		prog_find(lookup, nla_get_u32(xdp[IFLA_XDP_PROG_ID])); |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 	return NL_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void |  | ||||||
| net_find(struct xdp_map *lookup) |  | ||||||
| { |  | ||||||
| 	struct nl_msg *msg; |  | ||||||
|  |  | ||||||
| 	msg = unl_rtnl_msg(&unl, RTM_GETLINK, true); |  | ||||||
| 	msg->nm_nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); |  | ||||||
| 	unl_request(&unl, msg, getlink_recv, lookup); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void __attribute__((constructor)) |  | ||||||
| rtnl_init(void) |  | ||||||
| { |  | ||||||
| 	if (unl_rtnl_init(&unl)) |  | ||||||
| 		fprintf(stderr, "failed to open rtnl\n"); |  | ||||||
| } |  | ||||||
| @@ -1,67 +0,0 @@ | |||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| static inline __u64 ptr_to_u64(const void *ptr) |  | ||||||
| { |  | ||||||
| 	return (__u64)(unsigned long)ptr; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void |  | ||||||
| prog_find(struct xdp_map *lookup, __u32 prog) |  | ||||||
| { |  | ||||||
| 	__u32 id = 0; |  | ||||||
|  |  | ||||||
| 	while(true) { |  | ||||||
| 		struct bpf_prog_info info = {}; |  | ||||||
| 		__u32 len = sizeof(info); |  | ||||||
| 		int err; |  | ||||||
| 		int fd; |  | ||||||
|  |  | ||||||
| 		if (bpf_prog_get_next_id(id, &id)) { |  | ||||||
| 			if (errno != ENOENT) |  | ||||||
| 				fprintf(stderr, "bpf_prog_get_next_id failed\n"); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		if (id != prog) |  | ||||||
| 			continue; |  | ||||||
| 		fd = bpf_prog_get_fd_by_id(id); |  | ||||||
| 		if (fd < 0) { |  | ||||||
| 			if (errno == ENOENT) |  | ||||||
| 				continue; |  | ||||||
| 			fprintf(stderr, "bpf_prog_get_fd_by_id failed\n"); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		err = bpf_obj_get_info_by_fd(fd, &info, &len); |  | ||||||
| 		if (err) { |  | ||||||
| 			fprintf(stderr, "bpf_obj_get_info_by_fd failed\n"); |  | ||||||
| 			close(fd); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		if (info.name && !lookup) |  | ||||||
| 			fprintf(stderr, "\t%d: %s\n", id, info.name); |  | ||||||
| 		if (info.nr_map_ids) { |  | ||||||
| 			struct bpf_prog_info maps = {}; |  | ||||||
| 			__u32 len = sizeof(info); |  | ||||||
| 			__u32 map_ids[info.nr_map_ids]; |  | ||||||
| 			unsigned int i; |  | ||||||
| 			int err; |  | ||||||
|  |  | ||||||
| 			maps.nr_map_ids = info.nr_map_ids; |  | ||||||
| 			maps.map_ids = ptr_to_u64(map_ids); |  | ||||||
|  |  | ||||||
| 			err = bpf_obj_get_info_by_fd(fd, &maps, &len); |  | ||||||
| 			if (err || !maps.nr_map_ids) { |  | ||||||
| 				fprintf(stderr, "failed to get maps\n"); |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 			for (i = 0; i < info.nr_map_ids; i++) |  | ||||||
| 				map_find(lookup, map_ids[i]); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (!lookup) |  | ||||||
| 			fprintf(stderr, "\n"); |  | ||||||
| 		close(fd); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1,172 +0,0 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
|  |  | ||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| struct datarec { |  | ||||||
| 	__u64 rx_packets; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #ifndef XDP_ACTION_MAX |  | ||||||
| #define XDP_ACTION_MAX (XDP_REDIRECT + 1) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #define NANOSEC_PER_SEC 1000000000 /* 10^9 */ |  | ||||||
| static __u64 gettime(void) |  | ||||||
| { |  | ||||||
| 	struct timespec t; |  | ||||||
| 	int res; |  | ||||||
|  |  | ||||||
| 	res = clock_gettime(CLOCK_MONOTONIC, &t); |  | ||||||
| 	if (res < 0) { |  | ||||||
| 		fprintf(stderr, "Error with gettimeofday! (%i)\n", res); |  | ||||||
| 		exit(-1); |  | ||||||
| 	} |  | ||||||
| 	return (__u64) t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct record { |  | ||||||
| 	__u64 timestamp; |  | ||||||
| 	struct datarec total; /* defined in common_kern_user.h */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct stats_record { |  | ||||||
| 	struct record stats[1]; /* Assignment#2: Hint */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static double calc_period(struct record *r, struct record *p) |  | ||||||
| { |  | ||||||
| 	double period_ = 0; |  | ||||||
| 	__u64 period = 0; |  | ||||||
|  |  | ||||||
| 	period = r->timestamp - p->timestamp; |  | ||||||
| 	if (period > 0) |  | ||||||
| 		period_ = ((double) period / NANOSEC_PER_SEC); |  | ||||||
|  |  | ||||||
| 	return period_; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void stats_print(struct stats_record *stats_rec, |  | ||||||
| 			struct stats_record *stats_prev) |  | ||||||
| { |  | ||||||
| 	struct record *rec, *prev; |  | ||||||
| 	double period; |  | ||||||
| 	__u64 packets; |  | ||||||
| 	double pps; /* packets per sec */ |  | ||||||
|  |  | ||||||
| 	/* Assignment#2: Print other XDP actions stats  */ |  | ||||||
| 	{ |  | ||||||
| 		char *fmt = "%-12s %'11lld pkts (%'10.0f pps)" |  | ||||||
| 			//" %'11lld Kbytes (%'6.0f Mbits/s)" |  | ||||||
| 			" period:%f\n"; |  | ||||||
| 		const char *action = ""; |  | ||||||
| 		rec  = &stats_rec->stats[0]; |  | ||||||
| 		prev = &stats_prev->stats[0]; |  | ||||||
|  |  | ||||||
| 		period = calc_period(rec, prev); |  | ||||||
| 		if (period == 0) |  | ||||||
| 		       return; |  | ||||||
|  |  | ||||||
| 		packets = rec->total.rx_packets - prev->total.rx_packets; |  | ||||||
| 		pps     = packets / period; |  | ||||||
|  |  | ||||||
| 		printf(fmt, action, rec->total.rx_packets, pps, period); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* BPF_MAP_TYPE_ARRAY */ |  | ||||||
| static void map_get_value_array(int fd, __u32 key, struct datarec *value) |  | ||||||
| { |  | ||||||
| 	if ((bpf_map_lookup_elem(fd, &key, value)) != 0) { |  | ||||||
| 		fprintf(stderr, |  | ||||||
| 			"ERR: bpf_map_xdp_map_elem failed key:0x%X\n", key); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static bool map_collect(int fd, __u32 map_type, __u32 key, struct record *rec) |  | ||||||
| { |  | ||||||
| 	struct datarec value; |  | ||||||
|  |  | ||||||
| 	/* Get time as close as possible to reading map contents */ |  | ||||||
| 	rec->timestamp = gettime(); |  | ||||||
|  |  | ||||||
| 	switch (map_type) { |  | ||||||
| 	case BPF_MAP_TYPE_ARRAY: |  | ||||||
| 		map_get_value_array(fd, key, &value); |  | ||||||
| 		break; |  | ||||||
| 	case BPF_MAP_TYPE_PERCPU_ARRAY: |  | ||||||
| 		/* fall-through */ |  | ||||||
| 	default: |  | ||||||
| 		fprintf(stderr, "ERR: Unknown map_type(%u) cannot handle\n", |  | ||||||
| 			map_type); |  | ||||||
| 		return false; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* Assignment#1: Add byte counters */ |  | ||||||
| 	rec->total.rx_packets = value.rx_packets; |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void stats_collect(int map_fd, __u32 map_type, |  | ||||||
| 			  struct stats_record *stats_rec) |  | ||||||
| { |  | ||||||
| 	/* Assignment#2: Collect other XDP actions stats  */ |  | ||||||
| 	__u32 key = XDP_PASS; |  | ||||||
|  |  | ||||||
| 	map_collect(map_fd, map_type, key, &stats_rec->stats[0]); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void stats_poll(int map_fd, __u32 map_type, int interval) |  | ||||||
| { |  | ||||||
| 	struct stats_record prev, record = { 0 }; |  | ||||||
|  |  | ||||||
| 	/* Get initial reading quickly */ |  | ||||||
| 	stats_collect(map_fd, map_type, &record); |  | ||||||
| 	usleep(1000000/4); |  | ||||||
|  |  | ||||||
| 	while (1) { |  | ||||||
| 		prev = record; /* struct copy */ |  | ||||||
| 		stats_collect(map_fd, map_type, &record); |  | ||||||
| 		stats_print(&record, &prev); |  | ||||||
| 		sleep(interval); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| main(int argc, char **argv) |  | ||||||
| { |  | ||||||
| 	struct xdp_map xdp_map = { |  | ||||||
| 		.prog = "xdp_stats1_func", |  | ||||||
| 		.map = "xdp_stats_map", |  | ||||||
| 		.map_want = { |  | ||||||
| 			.key_size = sizeof(__u32), |  | ||||||
| 			.value_size = sizeof(struct datarec), |  | ||||||
| 			.max_entries = XDP_ACTION_MAX, |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| 	int interval = 2; |  | ||||||
| 	int ch; |  | ||||||
|  |  | ||||||
| 	while ((ch = getopt(argc, argv, "d:f:p:")) != -1) { |  | ||||||
| 		switch (ch) { |  | ||||||
| 		case 'd': |  | ||||||
| 			xdp_map.net = optarg; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			fprintf(stderr, "Invalid argument\n"); |  | ||||||
| 			exit(-1); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if (!xdp_map.net) { |  | ||||||
| 		fprintf(stderr, "invalid arguments\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (map_lookup(&xdp_map)) { |  | ||||||
| 		fprintf(stderr, "failed to xdp_map map\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	stats_poll(xdp_map.map_fd, xdp_map.map_info.type, interval); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @@ -1,79 +0,0 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
|  |  | ||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define SAMPLE_SIZE 64 |  | ||||||
|  |  | ||||||
| static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) |  | ||||||
| { |  | ||||||
| 	struct { |  | ||||||
| 		__u16 cookie; |  | ||||||
| 		__u16 pkt_len; |  | ||||||
| 		__u8  pkt_data[SAMPLE_SIZE]; |  | ||||||
| 	} __attribute__((packed)) *e = data; |  | ||||||
| 	int i; |  | ||||||
|  |  | ||||||
| 	fprintf(stderr, "%s:%s[%d]\n", __FILE__, __func__, __LINE__); |  | ||||||
| 	if (e->cookie != 0xdead) { |  | ||||||
| 		printf("BUG cookie %x sized %d\n", e->cookie, size); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len); |  | ||||||
| 	for (i = 0; i < 14 && i < e->pkt_len; i++) |  | ||||||
| 	printf("%02x ", e->pkt_data[i]); |  | ||||||
| 	printf("\n"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| main(int argc, char **argv) |  | ||||||
| { |  | ||||||
| 	struct xdp_map pkt_map = { |  | ||||||
| 		.prog = "uxdp_prog", |  | ||||||
| 		.map = "uxdp_pkts", |  | ||||||
| 		.map_want = { |  | ||||||
| 			.key_size = sizeof(__u32), |  | ||||||
| 			.value_size = sizeof(__u32), |  | ||||||
| 			.max_entries = 8, |  | ||||||
| 		}, |  | ||||||
| 	}; |  | ||||||
| 	struct perf_buffer_opts pb_opts = { |  | ||||||
| 		.sample_cb = print_bpf_output, |  | ||||||
| 	}; |  | ||||||
| 	struct perf_buffer *pb; |  | ||||||
| 	int ch; |  | ||||||
| 	int err; |  | ||||||
|  |  | ||||||
| 	while ((ch = getopt(argc, argv, "d:f:p:")) != -1) { |  | ||||||
| 		switch (ch) { |  | ||||||
| 		case 'd': |  | ||||||
| 			pkt_map.net = optarg; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			fprintf(stderr, "Invalid argument\n"); |  | ||||||
| 			exit(-1); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if (!pkt_map.net) { |  | ||||||
| 		fprintf(stderr, "invalid arguments\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (map_lookup(&pkt_map)) { |  | ||||||
| 		fprintf(stderr, "failed to xdp_map map\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	pb = perf_buffer__new(pkt_map.map_fd, 8, &pb_opts); |  | ||||||
| 	err = libbpf_get_error(pb); |  | ||||||
| 	if (err) { |  | ||||||
| 		perror("perf_buffer setup failed"); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	while (perf_buffer__poll(pb, 1000) >= 0) { |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @@ -1,50 +0,0 @@ | |||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <errno.h> |  | ||||||
| #include <getopt.h> |  | ||||||
| #include <locale.h> |  | ||||||
| #include <unistd.h> |  | ||||||
| #include <time.h> |  | ||||||
|  |  | ||||||
| #include <net/if.h> |  | ||||||
|  |  | ||||||
| #include <linux/limits.h> |  | ||||||
| #include <linux/if_xdp.h> |  | ||||||
| #include <linux/if_link.h> |  | ||||||
| #include <linux/if_xdp.h> |  | ||||||
|  |  | ||||||
| #include <bpf/bpf.h> |  | ||||||
| #include <bpf/libbpf.h> |  | ||||||
|  |  | ||||||
| #define PROG_MAX	64 |  | ||||||
| struct xdp_ctx { |  | ||||||
| 	char file[PATH_MAX]; |  | ||||||
| 	char progname[PROG_MAX]; |  | ||||||
| 	__u32 flags; |  | ||||||
| 	char ifindex; |  | ||||||
| 	struct bpf_object *obj; |  | ||||||
| 	struct bpf_program *prog; |  | ||||||
| 	int fd; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct xdp_map { |  | ||||||
| 	char *net; |  | ||||||
| 	char *prog; |  | ||||||
|  |  | ||||||
| 	char *map; |  | ||||||
| 	int map_fd; |  | ||||||
| 	int map_id; |  | ||||||
| 	struct bpf_map_info map_info; |  | ||||||
| 	struct bpf_map_info map_want; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| int xdp_load(struct xdp_ctx *ctx); |  | ||||||
| int xdp_detach(struct xdp_ctx *ctx); |  | ||||||
|  |  | ||||||
| int map_verify(struct bpf_map_info *map, struct bpf_map_info *exp); |  | ||||||
| int map_lookup(struct xdp_map *lookup); |  | ||||||
|  |  | ||||||
| void map_find(struct xdp_map *lookup, __u32 map); |  | ||||||
| void prog_find(struct xdp_map *lookup, __u32 prog); |  | ||||||
| void net_find(struct xdp_map *lookup); |  | ||||||
| @@ -1,67 +0,0 @@ | |||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| int |  | ||||||
| xdp_load(struct xdp_ctx *ctx) |  | ||||||
| { |  | ||||||
| 	struct bpf_prog_load_attr attr = { |  | ||||||
| 		.prog_type = BPF_PROG_TYPE_XDP, |  | ||||||
| 		.file = ctx->file, |  | ||||||
| 	}; |  | ||||||
| 	int err; |  | ||||||
| 	int fd = -1; |  | ||||||
|  |  | ||||||
| 	err = bpf_prog_load_xattr(&attr, &ctx->obj, &fd); |  | ||||||
| 	if (err) { |  | ||||||
| 		fprintf(stderr, "failed to load %s %s\n", ctx->file, strerror(-err)); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx->prog = bpf_object__find_program_by_title(ctx->obj, ctx->progname); |  | ||||||
| 	if (!ctx->prog) { |  | ||||||
| 		fprintf(stderr, "failed to find '%s'\n", ctx->progname); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx->fd = bpf_program__fd(ctx->prog); |  | ||||||
| 	if (ctx->fd <= 0) { |  | ||||||
| 		fprintf(stderr, "failed to get fd %s\n", ctx->progname); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	err = bpf_set_link_xdp_fd(ctx->ifindex, ctx->fd, ctx->flags); |  | ||||||
| 	if (err < 0) { |  | ||||||
| 		switch(err) { |  | ||||||
| 		case EBUSY: |  | ||||||
| 		case EEXIST: |  | ||||||
| 			fprintf(stderr, "program has already been loaded\n"); |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			fprintf(stderr, "failed to load program\n"); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| xdp_detach(struct xdp_ctx *ctx) |  | ||||||
| { |  | ||||||
| 	__u32 id; |  | ||||||
|  |  | ||||||
| 	if (bpf_get_link_xdp_id(ctx->ifindex, &id, ctx->flags)) { |  | ||||||
| 		fprintf(stderr, "xdp: failed to get link\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!id) |  | ||||||
| 		return 0; |  | ||||||
|  |  | ||||||
| 	if (bpf_set_link_xdp_fd(ctx->ifindex, -1, ctx->flags)) { |  | ||||||
| 		fprintf(stderr, "xdp: failed to detach\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @@ -1,12 +0,0 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
|  |  | ||||||
| #define _GNU_SOURCE |  | ||||||
|  |  | ||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| int |  | ||||||
| main(int argc, char **argv) |  | ||||||
| { |  | ||||||
| 	net_find(NULL); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @@ -1,56 +0,0 @@ | |||||||
| /* SPDX-License-Identifier: GPL-2.0 */ |  | ||||||
|  |  | ||||||
| #include "uxdp.h" |  | ||||||
|  |  | ||||||
| static int unload; |  | ||||||
|  |  | ||||||
| static void |  | ||||||
| parse_cmdline(int argc, char **argv, struct xdp_ctx *ctx) |  | ||||||
| { |  | ||||||
| 	int ch; |  | ||||||
|  |  | ||||||
| 	while ((ch = getopt(argc, argv, "d:f:p:u")) != -1) { |  | ||||||
| 		switch (ch) { |  | ||||||
| 		case 'd': |  | ||||||
| 			ctx->ifindex = if_nametoindex(optarg); |  | ||||||
| 			break; |  | ||||||
| 		case 'f': |  | ||||||
| 			strncpy(ctx->file, optarg, sizeof(ctx->file)); |  | ||||||
| 			break; |  | ||||||
| 		case 'p': |  | ||||||
| 			strncpy(ctx->progname, optarg, sizeof(ctx->progname)); |  | ||||||
| 			break; |  | ||||||
| 		case 'u': |  | ||||||
| 			unload = 1; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			fprintf(stderr, "Invalid argument\n"); |  | ||||||
| 			exit(-1); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| main(int argc, char **argv) |  | ||||||
| { |  | ||||||
| 	struct xdp_ctx ctx = { |  | ||||||
| 		.flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_SKB_MODE, |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	parse_cmdline(argc, argv, &ctx); |  | ||||||
|  |  | ||||||
| 	if (!ctx.ifindex) { |  | ||||||
| 		fprintf(stderr, "invalid device\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (unload) |  | ||||||
| 		return xdp_detach(&ctx); |  | ||||||
|  |  | ||||||
| 	if (!ctx.file[0] || !ctx.progname[0]) { |  | ||||||
| 		fprintf(stderr, "invalid program\n"); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return xdp_load(&ctx); |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user
	 John Crispin
					John Crispin