ubpf: drop feed

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2023-01-12 10:17:06 +01:00
parent b3589c92dc
commit 0737a706ec
11 changed files with 0 additions and 710 deletions

View File

@@ -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))

View File

@@ -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}
)

View File

@@ -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;
}

View File

@@ -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");
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}