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: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Ira Weiny 2019-03-19 14:11:49 -07:00 committed by Jason Gunthorpe
parent 2ccfbb70c2
commit 0ac01febd4
4 changed files with 271 additions and 0 deletions

View File

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

View File

@ -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
samples/bpf/ibumad_kern.c Normal file
View File

@ -0,0 +1,144 @@
// 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
samples/bpf/ibumad_user.c Normal file
View File

@ -0,0 +1,122 @@
// 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;
}