Skip to content

Commit

Permalink
samples/bpf: adjust bpf_tail_calls01 example
Browse files Browse the repository at this point in the history
After fixing issue in bpf_load.c I can finally test all
the different cases of my RFC patchset.

See email with patch :
 http://lkml.kernel.org/r/20170530115806.3086a009@redhat.com

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
  • Loading branch information
netoptimizer committed May 29, 2017
1 parent e785522 commit 8f5d3e6
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 63 deletions.
41 changes: 24 additions & 17 deletions kernel/samples/bpf/bpf_tail_calls01_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ char _license[] SEC("license") = "GPL";
#define bpf_debug(fmt, ...) { } while (0)
#endif

struct bpf_map_def SEC("maps") jmp_table = {
struct bpf_map_def SEC("maps") jmp_table1 = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u32),
.max_entries = 8,
.max_entries = 100,
};

struct bpf_map_def SEC("maps") jmp_table2 = {
Expand All @@ -37,6 +37,12 @@ struct bpf_map_def SEC("maps") jmp_table2 = {
.max_entries = 1000,
};

struct bpf_map_def SEC("maps") jmp_table3 = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u32),
.max_entries = 100,
};

/* Main/root ebpf xdp program */
SEC("xdp")
Expand All @@ -52,7 +58,7 @@ int xdp_prog(struct xdp_md *ctx)
if (eth + 1 > data_end)
return XDP_ABORTED;

bpf_tail_call(ctx, &jmp_table, 1);
bpf_tail_call(ctx, &jmp_table1, 1);

/* bpf_tail_call on empty jmp_table entry, cause fall-through.
* (Normally a bpf_tail_call never returns)
Expand All @@ -68,40 +74,39 @@ int xdp_prog(struct xdp_md *ctx)
*/

/* Tail call index=1 */
SEC("xdp/1")
int xdp_some_tail_call_name(struct xdp_md *ctx)
SEC("xdp_1")
int xdp_tail_call_1(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;

bpf_debug("XDP: tail call id=1\n");
bpf_debug("XDP: tail call (xdp_1) id=1\n");

bpf_tail_call(ctx, &jmp_table, 5);
bpf_tail_call(ctx, &jmp_table1, 5);

return XDP_PASS;
}

/* Tail call index=5 */
SEC("xdp/5")
int xdp_random_tail_call_name(struct xdp_md *ctx)
SEC("xdp_5")
int xdp_tail_call_2(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
volatile u32 hash = 0;

// using experimental rx_hash feature
// hash = ctx->rxhash;
bpf_debug("XDP: tail call id=5 hash=%u\n", hash);
//hash = ctx->rxhash;
bpf_debug("XDP: tail call (xdp_5) id=5 hash=%u\n", hash);

bpf_tail_call(ctx, &jmp_table2, 42);
// bpf_tail_call(ctx, &jmp_table2, 0);
return XDP_PASS;
}

/* Another tail call */
SEC("xdp_test")
int xdp_another_tail_call(struct xdp_md *ctx)
SEC("xdp_unrelated")
int xdp_some_tail_call_3(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
Expand All @@ -110,9 +115,11 @@ int xdp_another_tail_call(struct xdp_md *ctx)

// using experimental rx_hash feature
hash = ctx->rxhash;
bpf_debug("XDP: xdp_another_tail_call hash=%u\n", hash);
bpf_debug("XDP: tail call 'xdp_unrelated' hash=%u\n", hash);

//bpf_tail_call(ctx, &jmp_table1, 1); // Can give loop (capped runtime)

// none existing jmp entry, just to reference map
bpf_tail_call(ctx, &jmp_table3, 0);
bpf_tail_call(ctx, &jmp_table2, 0);
return XDP_PASS;
}
121 changes: 75 additions & 46 deletions kernel/samples/bpf/bpf_tail_calls01_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ static const char *__doc__= " Test of bpf_tail_call from XDP program\n\n"
#include <getopt.h>
#include <signal.h>
#include <net/if.h>

#include <unistd.h>
#include <linux/if_link.h>

#include "libbpf.h"
Expand All @@ -18,12 +18,14 @@ static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char *ifname = NULL;
static __u32 xdp_flags = 0;
static bool debug = false;

/* Exit return codes */
#define EXIT_OK 0
#define EXIT_FAIL 1
#define EXIT_FAIL_OPTION 2
#define EXIT_FAIL_XDP 3
#define EXIT_FAIL_MAP 20

static void int_exit(int sig)
{
Expand Down Expand Up @@ -64,15 +66,56 @@ static void usage(char *argv[])
printf("\n");
}

/* Helper for adding prog to prog_map */
void jmp_table_add_prog(int map_jmp_table_idx, int idx, int prog_idx)
{
int jmp_table_fd = map_fd[map_jmp_table_idx];
int prog = prog_fd[prog_idx];
int err;

if (prog == 0) {
printf("ERR: Invalid zero-FD prog_fd[%d]=%d,"
" did bpf_load.c fail loading program?!?\n",
prog_idx, prog);
exit(EXIT_FAIL_MAP);
}

err = bpf_map_update_elem(jmp_table_fd, &idx, &prog, 0);
if (err) {
printf("ERR(%d/%d): Fail add prog_fd[%d]=%d to jmp_table%d i:%d\n",
err, errno, prog_idx, prog, map_jmp_table_idx+1, idx);
exit(EXIT_FAIL_MAP);
}
if (debug) {
printf("Add XDP prog_fd[%d]=%d to jmp_table%d idx:%d\n",
prog_idx, prog, map_jmp_table_idx+1, idx);
}
}

int main(int argc, char **argv)
{
char filename[256];
bool debug = false;
int longindex = 0;
int opt;
int opt, i;

/* Corresponding map_fd[index] for jump tables aka tail calls */
int jmp_table1 = 0;
int jmp_table2 = 1;
int jmp_table3 = 2;

/*
* WARNING: There were an issue in bpf_load.c that caused bpf
* prog section order in prog_fd[] to get mixed up (if prog
* didn't reference a map)
*
* Corresponding prog_fd[index] for prog section tail calls.
*/
int prog_xdp_1 = 1;
int prog_xdp_5 = 2;
int prog_xdp_unrelated = 3;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
/* Parse commands line args */
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hd:",
long_options, &longindex)) != -1) {
switch (opt) {
Expand Down Expand Up @@ -137,26 +180,8 @@ int main(int argc, char **argv)
* order of SEC map and prog definitions.
*/
if (1) {
int jmp_table_fd = map_fd[0];
int xdp_prog1 = prog_fd[1];
int xdp_prog5 = prog_fd[2];
int idx; /* index in tail call jmp_table */
int err;

if (debug)
printf("XXX: FDs xdp_prog0:%d xdp_prog5:%d jmp:%d\n",
xdp_prog1, xdp_prog5, jmp_table_fd);

idx = 1;
err = bpf_map_update_elem(jmp_table_fd, &idx, &xdp_prog1, 0);
if (err) {
printf("ERR: Fail add jmp to xdp_prog1 err:%d\n", err);
}
idx = 5;
err = bpf_map_update_elem(jmp_table_fd, &idx, &xdp_prog5, 0);
if (err) {
printf("ERR: Fail add jmp to xdp_prog5 err:%d\n", err);
}
jmp_table_add_prog(jmp_table1, 1, prog_xdp_1);
jmp_table_add_prog(jmp_table1, 5, prog_xdp_5);
}
/* Notice populating jmp_table is done _before_ attaching the
* main XDP program to a specific device.
Expand All @@ -165,17 +190,15 @@ int main(int argc, char **argv)
* changes after a XDP program have been associated with a
* device.
*/
if (0) { /* Notice jmp_table2 (number 2) */
int jmp_table2 = map_fd[1];
int prog = prog_fd[3]; /* xdp_another_tail_call */
int i; /* index in tail call jmp_table2 */
int err;

for (i = 40; i < 50; i++) {
err = bpf_map_update_elem(jmp_table2, &i, &prog, 0);
if (err)
printf("ERR: Fail add jmp_table2 err:%d\n",err);
}
if (1) { /* Notice jmp_table2 (number 2) */
for (i = 40; i < 50; i++)
jmp_table_add_prog(jmp_table2, i, prog_xdp_unrelated);
}

if (debug) {
printf("map_fd[] jmp_table file descriptor mapping:\n");
for (i = 0; i < 3; i++)
printf(" jmp_table map_fd[%d]=fd:%d\n", i, map_fd[i]);
}

/* Attach XDP program */
Expand All @@ -184,26 +207,32 @@ int main(int argc, char **argv)
return EXIT_FAIL_XDP;
}

/* Remove XDP program when program is interrupted or killed */
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);

/* Notice, after XDP prog have been attached, the features
* have been "locked down" (in RFC patch). Adding something
* to a jmp_table will result in runtime validation.
*/
if (1) {
int jmp_table2 = map_fd[1];
int prog = prog_fd[3]; /* xdp_another_tail_call */
int i; /* index in tail call jmp_table2 */
int err;

if (1) {
/* Populate jmp_table3 with some prog */
for (i = 30; i < 32; i++) {
err = bpf_map_update_elem(jmp_table2, &i, &prog, 0);
if (err)
printf("ERR: Fail add jmp_table2 err:%d\n",err);
jmp_table_add_prog(jmp_table3, i, prog_xdp_unrelated);
}
}

/* Remove XDP program when program is interrupted or killed */
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
if (1) {
/* Take over jmp entry 5 */
if (debug) {
int delay = 2;
printf("Delay: %d sec, before taking over idx 5\n",
delay);
sleep(delay);
}
jmp_table_add_prog(jmp_table1, 5, prog_xdp_unrelated);
}

if (debug) {
printf("Debug-mode reading trace pipe (fix #define DEBUG)\n");
Expand Down

0 comments on commit 8f5d3e6

Please sign in to comment.