aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf/libbpf.c
diff options
context:
space:
mode:
authorJoe Stringer <joe@ovn.org>2017-01-26 16:19:56 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-01-31 14:20:05 -0500
commitf367540c8c13d65603c431e29a0b87a7db893d6c (patch)
tree7a5556430a8d34e5a0ba7accbcfcdfcc206a5fb1 /tools/lib/bpf/libbpf.c
parent9c68ae98c6f714ef573826cfc9055af1bd5e97b1 (diff)
tools lib bpf: Add BPF program pinning APIs
Add new APIs to pin a BPF program (or specific instances) to the filesystem. The user can specify the path full path within a BPF filesystem to pin the program. bpf_program__pin_instance(prog, path, n) will pin the nth instance of 'prog' to the specified path. bpf_program__pin(prog, path) will create the directory 'path' (if it does not exist) and pin each instance within that directory. For instance, path/0, path/1, path/2. Committer notes: - Add missing headers for mkdir() - Check strdup() for failure - Check snprintf >= size, not >, as == also means truncated, see 'man snprintf', return value. - Conditionally define BPF_FS_MAGIC, as it isn't in magic.h in older systems and we're not yet having a tools/include/uapi/linux/magic.h copy. - Do not include linux/magic.h, not present in older distros. Signed-off-by: Joe Stringer <joe@ovn.org> Cc: Alexei Starovoitov <ast@fb.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: Wang Nan <wangnan0@huawei.com> Cc: netdev@vger.kernel.org Link: http://lkml.kernel.org/r/20170126212001.14103-2-joe@ovn.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r--tools/lib/bpf/libbpf.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e6cd62b1264b..c4465b2fddf6 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 * Copyright (C) 2017 Nicira, Inc.
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public 10 * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,7 @@
22#include <stdlib.h> 23#include <stdlib.h>
23#include <stdio.h> 24#include <stdio.h>
24#include <stdarg.h> 25#include <stdarg.h>
26#include <libgen.h>
25#include <inttypes.h> 27#include <inttypes.h>
26#include <string.h> 28#include <string.h>
27#include <unistd.h> 29#include <unistd.h>
@@ -32,6 +34,10 @@
32#include <linux/kernel.h> 34#include <linux/kernel.h>
33#include <linux/bpf.h> 35#include <linux/bpf.h>
34#include <linux/list.h> 36#include <linux/list.h>
37#include <linux/limits.h>
38#include <sys/stat.h>
39#include <sys/types.h>
40#include <sys/vfs.h>
35#include <libelf.h> 41#include <libelf.h>
36#include <gelf.h> 42#include <gelf.h>
37 43
@@ -42,6 +48,10 @@
42#define EM_BPF 247 48#define EM_BPF 247
43#endif 49#endif
44 50
51#ifndef BPF_FS_MAGIC
52#define BPF_FS_MAGIC 0xcafe4a11
53#endif
54
45#define __printf(a, b) __attribute__((format(printf, a, b))) 55#define __printf(a, b) __attribute__((format(printf, a, b)))
46 56
47__printf(1, 2) 57__printf(1, 2)
@@ -1237,6 +1247,116 @@ out:
1237 return err; 1247 return err;
1238} 1248}
1239 1249
1250static int check_path(const char *path)
1251{
1252 struct statfs st_fs;
1253 char *dname, *dir;
1254 int err = 0;
1255
1256 if (path == NULL)
1257 return -EINVAL;
1258
1259 dname = strdup(path);
1260 if (dname == NULL)
1261 return -ENOMEM;
1262
1263 dir = dirname(dname);
1264 if (statfs(dir, &st_fs)) {
1265 pr_warning("failed to statfs %s: %s\n", dir, strerror(errno));
1266 err = -errno;
1267 }
1268 free(dname);
1269
1270 if (!err && st_fs.f_type != BPF_FS_MAGIC) {
1271 pr_warning("specified path %s is not on BPF FS\n", path);
1272 err = -EINVAL;
1273 }
1274
1275 return err;
1276}
1277
1278int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
1279 int instance)
1280{
1281 int err;
1282
1283 err = check_path(path);
1284 if (err)
1285 return err;
1286
1287 if (prog == NULL) {
1288 pr_warning("invalid program pointer\n");
1289 return -EINVAL;
1290 }
1291
1292 if (instance < 0 || instance >= prog->instances.nr) {
1293 pr_warning("invalid prog instance %d of prog %s (max %d)\n",
1294 instance, prog->section_name, prog->instances.nr);
1295 return -EINVAL;
1296 }
1297
1298 if (bpf_obj_pin(prog->instances.fds[instance], path)) {
1299 pr_warning("failed to pin program: %s\n", strerror(errno));
1300 return -errno;
1301 }
1302 pr_debug("pinned program '%s'\n", path);
1303
1304 return 0;
1305}
1306
1307static int make_dir(const char *path)
1308{
1309 int err = 0;
1310
1311 if (mkdir(path, 0700) && errno != EEXIST)
1312 err = -errno;
1313
1314 if (err)
1315 pr_warning("failed to mkdir %s: %s\n", path, strerror(-err));
1316 return err;
1317}
1318
1319int bpf_program__pin(struct bpf_program *prog, const char *path)
1320{
1321 int i, err;
1322
1323 err = check_path(path);
1324 if (err)
1325 return err;
1326
1327 if (prog == NULL) {
1328 pr_warning("invalid program pointer\n");
1329 return -EINVAL;
1330 }
1331
1332 if (prog->instances.nr <= 0) {
1333 pr_warning("no instances of prog %s to pin\n",
1334 prog->section_name);
1335 return -EINVAL;
1336 }
1337
1338 err = make_dir(path);
1339 if (err)
1340 return err;
1341
1342 for (i = 0; i < prog->instances.nr; i++) {
1343 char buf[PATH_MAX];
1344 int len;
1345
1346 len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
1347 if (len < 0)
1348 return -EINVAL;
1349 else if (len >= PATH_MAX)
1350 return -ENAMETOOLONG;
1351
1352 err = bpf_program__pin_instance(prog, buf, i);
1353 if (err)
1354 return err;
1355 }
1356
1357 return 0;
1358}
1359
1240void bpf_object__close(struct bpf_object *obj) 1360void bpf_object__close(struct bpf_object *obj)
1241{ 1361{
1242 size_t i; 1362 size_t i;