Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ac01feb authored by Ira Weiny's avatar Ira Weiny Committed by Jason Gunthorpe
Browse files

BPF: Add sample code for new ib_umad tracepoint



Provide a count of class types for a summary of MAD packets.  The example
shows one way to filter the trace data based on management class.

Signed-off-by: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 2ccfbb70
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7655,6 +7655,8 @@ F: include/uapi/rdma/
F:	include/rdma/
F:	include/trace/events/ib_mad.h
F:	include/trace/events/ib_umad.h
F:	samples/bpf/ibumad_kern.c
F:	samples/bpf/ibumad_user.c

INGENIC JZ4780 DMA Driver
M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+3 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ hostprogs-y += xdpsock
hostprogs-y += xdp_fwd
hostprogs-y += task_fd_query
hostprogs-y += xdp_sample_pkts
hostprogs-y += ibumad
hostprogs-y += hbm

# Libbpf dependencies
@@ -108,6 +109,7 @@ xdpsock-objs := xdpsock_user.o
xdp_fwd-objs := xdp_fwd_user.o
task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS)
hbm-objs := bpf_load.o hbm.o $(CGROUP_HELPERS)

# Tell kbuild to always build the programs
@@ -166,6 +168,7 @@ always += xdp_adjust_tail_kern.o
always += xdp_fwd_kern.o
always += task_fd_query_kern.o
always += xdp_sample_pkts_kern.o
always += ibumad_kern.o
always += hbm_out_kern.o

KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include
+144 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB

/**
 * ibumad BPF sample kernel side
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * Copyright(c) 2018 Ira Weiny, Intel Corporation
 */

#define KBUILD_MODNAME "ibumad_count_pkts_by_class"
#include <uapi/linux/bpf.h>

#include "bpf_helpers.h"


struct bpf_map_def SEC("maps") read_count = {
	.type        = BPF_MAP_TYPE_ARRAY,
	.key_size    = sizeof(u32), /* class; u32 required */
	.value_size  = sizeof(u64), /* count of mads read */
	.max_entries = 256, /* Room for all Classes */
};

struct bpf_map_def SEC("maps") write_count = {
	.type        = BPF_MAP_TYPE_ARRAY,
	.key_size    = sizeof(u32), /* class; u32 required */
	.value_size  = sizeof(u64), /* count of mads written */
	.max_entries = 256, /* Room for all Classes */
};

#undef DEBUG
#ifdef DEBUG
#define bpf_debug(fmt, ...)                         \
({                                                  \
	char ____fmt[] = fmt;                       \
	bpf_trace_printk(____fmt, sizeof(____fmt),  \
			 ##__VA_ARGS__);            \
})
#else
#define bpf_debug(fmt, ...)
#endif

/* Taken from the current format defined in
 * include/trace/events/ib_umad.h
 * and
 * /sys/kernel/debug/tracing/events/ib_umad/ib_umad_read/format
 * /sys/kernel/debug/tracing/events/ib_umad/ib_umad_write/format
 */
struct ib_umad_rw_args {
	u64 pad;
	u8 port_num;
	u8 sl;
	u8 path_bits;
	u8 grh_present;
	u32 id;
	u32 status;
	u32 timeout_ms;
	u32 retires;
	u32 length;
	u32 qpn;
	u32 qkey;
	u8 gid_index;
	u8 hop_limit;
	u16 lid;
	u16 attr_id;
	u16 pkey_index;
	u8 base_version;
	u8 mgmt_class;
	u8 class_version;
	u8 method;
	u32 flow_label;
	u16 mad_status;
	u16 class_specific;
	u32 attr_mod;
	u64 tid;
	u8 gid[16];
	u32 dev_index;
	u8 traffic_class;
};

SEC("tracepoint/ib_umad/ib_umad_read_recv")
int on_ib_umad_read_recv(struct ib_umad_rw_args *ctx)
{
	u64 zero = 0, *val;
	u8 class = ctx->mgmt_class;

	bpf_debug("ib_umad read recv : class 0x%x\n", class);

	val = bpf_map_lookup_elem(&read_count, &class);
	if (!val) {
		bpf_map_update_elem(&read_count, &class, &zero, BPF_NOEXIST);
		val = bpf_map_lookup_elem(&read_count, &class);
		if (!val)
			return 0;
	}

	(*val) += 1;

	return 0;
}
SEC("tracepoint/ib_umad/ib_umad_read_send")
int on_ib_umad_read_send(struct ib_umad_rw_args *ctx)
{
	u64 zero = 0, *val;
	u8 class = ctx->mgmt_class;

	bpf_debug("ib_umad read send : class 0x%x\n", class);

	val = bpf_map_lookup_elem(&read_count, &class);
	if (!val) {
		bpf_map_update_elem(&read_count, &class, &zero, BPF_NOEXIST);
		val = bpf_map_lookup_elem(&read_count, &class);
		if (!val)
			return 0;
	}

	(*val) += 1;

	return 0;
}
SEC("tracepoint/ib_umad/ib_umad_write")
int on_ib_umad_write(struct ib_umad_rw_args *ctx)
{
	u64 zero = 0, *val;
	u8 class = ctx->mgmt_class;

	bpf_debug("ib_umad write : class 0x%x\n", class);

	val = bpf_map_lookup_elem(&write_count, &class);
	if (!val) {
		bpf_map_update_elem(&write_count, &class, &zero, BPF_NOEXIST);
		val = bpf_map_lookup_elem(&write_count, &class);
		if (!val)
			return 0;
	}

	(*val) += 1;

	return 0;
}

char _license[] SEC("license") = "GPL";
+122 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB

/**
 * ibumad BPF sample user side
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * Copyright(c) 2018 Ira Weiny, Intel Corporation
 */

#include <linux/bpf.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <limits.h>

#include <sys/resource.h>
#include <getopt.h>
#include <net/if.h>

#include "bpf_load.h"
#include "bpf_util.h"
#include "bpf/libbpf.h"

static void dump_counts(int fd)
{
	__u32 key;
	__u64 value;

	for (key = 0; key < 256; key++) {
		if (bpf_map_lookup_elem(fd, &key, &value)) {
			printf("failed to read key %u\n", key);
			continue;
		}
		if (value)
			printf("0x%02x : %llu\n", key, value);
	}
}

static void dump_all_counts(void)
{
	printf("Read 'Class : count'\n");
	dump_counts(map_fd[0]);
	printf("Write 'Class : count'\n");
	dump_counts(map_fd[1]);
}

static void dump_exit(int sig)
{
	dump_all_counts();
	exit(0);
}

static const struct option long_options[] = {
	{"help",      no_argument,       NULL, 'h'},
	{"delay",     required_argument, NULL, 'd'},
};

static void usage(char *cmd)
{
	printf("eBPF test program to count packets from various IP addresses\n"
		"Usage: %s <options>\n"
		"       --help,   -h  this menu\n"
		"       --delay,  -d  <delay>  wait <delay> sec between prints [1 - 1000000]\n"
		, cmd
		);
}

int main(int argc, char **argv)
{
	unsigned long delay = 5;
	int longindex = 0;
	int opt;
	char bpf_file[256];

	/* Create the eBPF kernel code path name.
	 * This follows the pattern of all of the other bpf samples
	 */
	snprintf(bpf_file, sizeof(bpf_file), "%s_kern.o", argv[0]);

	/* Do one final dump when exiting */
	signal(SIGINT, dump_exit);
	signal(SIGTERM, dump_exit);

	while ((opt = getopt_long(argc, argv, "hd:rSw",
				  long_options, &longindex)) != -1) {
		switch (opt) {
		case 'd':
			delay = strtoul(optarg, NULL, 0);
			if (delay == ULONG_MAX || delay < 0 ||
			    delay > 1000000) {
				fprintf(stderr, "ERROR: invalid delay : %s\n",
					optarg);
				usage(argv[0]);
				return 1;
			}
			break;
		default:
		case 'h':
			usage(argv[0]);
			return 1;
		}
	}

	if (load_bpf_file(bpf_file)) {
		fprintf(stderr, "ERROR: failed to load eBPF from file : %s\n",
			bpf_file);
		return 1;
	}

	while (1) {
		sleep(delay);
		dump_all_counts();
	}

	return 0;
}