Skip to content

Commit

Permalink
BPF: Add sample code for new ib_umad tracepoint
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
  • Loading branch information
weiny2 authored and jgunthorpe committed Mar 27, 2019
1 parent 2ccfbb7 commit 0ac01fe
Show file tree
Hide file tree
Showing 4 changed files with 271 additions and 0 deletions.
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
Expand Down
3 changes: 3 additions & 0 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
144 changes: 144 additions & 0 deletions samples/bpf/ibumad_kern.c
Original file line number Diff line number Diff line change
@@ -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 changes: 122 additions & 0 deletions samples/bpf/ibumad_user.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 0ac01fe

Please sign in to comment.