Skip to content

Commit b941ce5

Browse files
authored
Merge pull request #57 from aspsk/basic-solutions
Basic solutions
2 parents 9e52f78 + 4b38ce9 commit b941ce5

File tree

13 files changed

+712
-71
lines changed

13 files changed

+712
-71
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
22

3-
LESSONS = $(wildcard basic??-*) $(wildcard packet*) $(wildcard tracing??-*)
3+
LESSONS = $(wildcard basic*) $(wildcard packet*) $(wildcard tracing??-*)
44
LESSONS_CLEAN = $(addsuffix _clean,$(LESSONS))
55

66
.PHONY: clean $(LESSONS) $(LESSONS_CLEAN)

basic-solutions/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
3+
USER_TARGETS := xdp_stats xdp_loader
4+
5+
LIBBPF_DIR = ../libbpf/src/
6+
COMMON_DIR = ../common/
7+
8+
# Extend with another COMMON_OBJS
9+
COMMON_OBJS += $(COMMON_DIR)/common_libbpf.o
10+
11+
include $(COMMON_DIR)/common.mk

basic-solutions/README.org

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# -*- fill-column: 76; -*-
2+
#+TITLE: Tutorial: Packet - solutions
3+
#+OPTIONS: ^:nil
4+
5+
This directory contains solutions to all the assignments in the
6+
[[file:../basic01-xdp-pass/][basic01]],
7+
[[file:../basic02-prog-by-name/][basic02]],
8+
[[file:../basic03-map-counter/][basic03]], and
9+
[[file:../basic04-pinning-maps/][basic04]] lessons.
10+
11+
* Table of Contents :TOC:
12+
- [[#solutions][Solutions]]
13+
- [[#basic01-loading-your-first-bpf-program][Basic01: loading your first BPF program]]
14+
- [[#basic02-loading-a-program-by-name][Basic02: loading a program by name]]
15+
- [[#basic03-counting-with-bpf-maps][Basic03: counting with BPF maps]]
16+
- [[#basic04-pinning-of-maps][Basic04: pinning of maps]]
17+
18+
* Solutions
19+
20+
** Basic01: loading your first BPF program
21+
22+
This lesson doesn't contain any assignments except to repeat the steps listed
23+
in the lesson readme file.
24+
25+
** Basic02: loading a program by name
26+
27+
*** Assignment 1: Setting up your test lab
28+
29+
No code is needed, just repeat the steps listed in the assignment description.
30+
31+
*** Assignment 2: Add xdp_abort program
32+
33+
Just add the following section to the
34+
[[file:../basic02-prog-by-name/xdp_prog_kern.c][xdp_prog_kern.c]] program and
35+
follow the steps listed in the assignment description:
36+
#+begin_example c
37+
SEC("xdp_abort")
38+
int xdp_abort_func(struct xdp_md *ctx)
39+
{
40+
return XDP_ABORTED;
41+
}
42+
#+end_example
43+
44+
** Basic03: counting with BPF maps
45+
46+
The solutions to all three assignments can be found in the following files:
47+
48+
* The [[file:../basic04-pinning-maps/common_kern_user.h][common_kern_user.h]] file contains the new structure =datarec= definition.
49+
* The [[file:../basic04-pinning-maps/xdp_prog_kern.c][xdp_prog_kern.c]] file contains the new =xdp_stats_map= map definition and the updated =xdp_stats_record_action= function.
50+
51+
Note that for use in later lessons/assignments the code was moved to the following files:
52+
[[file:../common/xdp_stats_kern_user.h][xdp_stats_kern_user.h]] and
53+
[[file:../common/xdp_stats_kern.h][xdp_stats_kern.h]]. So in order to use the
54+
=xdp_stats_record_action= function in later XDP programs, just include the
55+
following header files:
56+
#+begin_example c
57+
#include "../common/xdp_stats_kern_user.h"
58+
#include "../common/xdp_stats_kern.h"
59+
#+end_example
60+
For a user-space application, only the former header is needed.
61+
62+
** Basic04: pinning of maps
63+
64+
*** Assignment 1: (xdp_stats.c) reload map file-descriptor
65+
66+
See the [[file:xdp_stats.c][xdp_stats.c]] program in this directory.
67+
68+
*** Assignment 2: (xdp_loader.c) reuse pinned map
69+
70+
See the [[file:xdp_loader.c][xdp_loader.c]] program in this directory.

basic-solutions/xdp_loader.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
static const char *__doc__ = "XDP loader\n"
3+
" - Allows selecting BPF section --progsec name to XDP-attach to --dev\n";
4+
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <errno.h>
9+
#include <getopt.h>
10+
11+
#include <locale.h>
12+
#include <unistd.h>
13+
#include <time.h>
14+
15+
#include <bpf/bpf.h>
16+
#include <bpf/libbpf.h>
17+
18+
#include <net/if.h>
19+
#include <linux/if_link.h> /* depend on kernel-headers installed */
20+
21+
#include "../common/common_params.h"
22+
#include "../common/common_user_bpf_xdp.h"
23+
#include "../common/common_libbpf.h"
24+
25+
static const char *default_filename = "xdp_prog_kern.o";
26+
27+
static const struct option_wrapper long_options[] = {
28+
29+
{{"help", no_argument, NULL, 'h' },
30+
"Show help", false},
31+
32+
{{"dev", required_argument, NULL, 'd' },
33+
"Operate on device <ifname>", "<ifname>", true},
34+
35+
{{"skb-mode", no_argument, NULL, 'S' },
36+
"Install XDP program in SKB (AKA generic) mode"},
37+
38+
{{"native-mode", no_argument, NULL, 'N' },
39+
"Install XDP program in native mode"},
40+
41+
{{"auto-mode", no_argument, NULL, 'A' },
42+
"Auto-detect SKB or native mode"},
43+
44+
{{"force", no_argument, NULL, 'F' },
45+
"Force install, replacing existing program on interface"},
46+
47+
{{"unload", no_argument, NULL, 'U' },
48+
"Unload XDP program instead of loading"},
49+
50+
{{"reuse-maps", no_argument, NULL, 'M' },
51+
"Reuse pinned maps"},
52+
53+
{{"quiet", no_argument, NULL, 'q' },
54+
"Quiet mode (no output)"},
55+
56+
{{"filename", required_argument, NULL, 1 },
57+
"Load program from <file>", "<file>"},
58+
59+
{{"progsec", required_argument, NULL, 2 },
60+
"Load program in <section> of the ELF file", "<section>"},
61+
62+
{{0, 0, NULL, 0 }, NULL, false}
63+
};
64+
65+
#ifndef PATH_MAX
66+
#define PATH_MAX 4096
67+
#endif
68+
69+
const char *pin_basedir = "/sys/fs/bpf";
70+
const char *map_name = "xdp_stats_map";
71+
72+
/* Pinning maps under /sys/fs/bpf in subdir */
73+
int pin_maps_in_bpf_object(struct bpf_object *bpf_obj, struct config *cfg)
74+
{
75+
char map_filename[PATH_MAX];
76+
int err, len;
77+
78+
len = snprintf(map_filename, PATH_MAX, "%s/%s/%s",
79+
pin_basedir, cfg->ifname, map_name);
80+
if (len < 0) {
81+
fprintf(stderr, "ERR: creating map_name\n");
82+
return EXIT_FAIL_OPTION;
83+
}
84+
85+
/* Existing/previous XDP prog might not have cleaned up */
86+
if (access(map_filename, F_OK ) != -1 ) {
87+
if (verbose)
88+
printf(" - Unpinning (remove) prev maps in %s/\n",
89+
cfg->pin_dir);
90+
91+
/* Basically calls unlink(3) on map_filename */
92+
err = bpf_object__unpin_maps(bpf_obj, cfg->pin_dir);
93+
if (err) {
94+
fprintf(stderr, "ERR: UNpinning maps in %s\n", cfg->pin_dir);
95+
return EXIT_FAIL_BPF;
96+
}
97+
}
98+
if (verbose)
99+
printf(" - Pinning maps in %s/\n", cfg->pin_dir);
100+
101+
/* This will pin all maps in our bpf_object */
102+
err = bpf_object__pin_maps(bpf_obj, cfg->pin_dir);
103+
if (err)
104+
return EXIT_FAIL_BPF;
105+
106+
return 0;
107+
}
108+
109+
int main(int argc, char **argv)
110+
{
111+
struct bpf_object *bpf_obj;
112+
int err, len;
113+
114+
struct config cfg = {
115+
.xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_DRV_MODE,
116+
.ifindex = -1,
117+
.do_unload = false,
118+
};
119+
/* Set default BPF-ELF object file and BPF program name */
120+
strncpy(cfg.filename, default_filename, sizeof(cfg.filename));
121+
/* Cmdline options can change progsec */
122+
parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);
123+
124+
/* Required option */
125+
if (cfg.ifindex == -1) {
126+
fprintf(stderr, "ERR: required option --dev missing\n\n");
127+
usage(argv[0], __doc__, long_options, (argc == 1));
128+
return EXIT_FAIL_OPTION;
129+
}
130+
if (cfg.do_unload) {
131+
if (!cfg.reuse_maps) {
132+
/* TODO: Miss unpin of maps on unload */
133+
}
134+
return xdp_link_detach(cfg.ifindex, cfg.xdp_flags, 0);
135+
}
136+
137+
len = snprintf(cfg.pin_dir, PATH_MAX, "%s/%s", pin_basedir, cfg.ifname);
138+
if (len < 0) {
139+
fprintf(stderr, "ERR: creating pin dirname\n");
140+
return EXIT_FAIL_OPTION;
141+
}
142+
143+
144+
bpf_obj = load_bpf_and_xdp_attach(&cfg);
145+
if (!bpf_obj)
146+
return EXIT_FAIL_BPF;
147+
148+
if (verbose) {
149+
printf("Success: Loaded BPF-object(%s) and used section(%s)\n",
150+
cfg.filename, cfg.progsec);
151+
printf(" - XDP prog attached on device:%s(ifindex:%d)\n",
152+
cfg.ifname, cfg.ifindex);
153+
}
154+
155+
/* Use the --dev name as subdir for exporting/pinning maps */
156+
if (!cfg.reuse_maps) {
157+
err = pin_maps_in_bpf_object(bpf_obj, &cfg);
158+
if (err) {
159+
fprintf(stderr, "ERR: pinning maps\n");
160+
return err;
161+
}
162+
}
163+
164+
return EXIT_OK;
165+
}

0 commit comments

Comments
 (0)