aboutsummaryrefslogtreecommitdiffstats
path: root/tools/bpf/bpftool/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bpf/bpftool/common.c')
-rw-r--r--tools/bpf/bpftool/common.c195
1 files changed, 164 insertions, 31 deletions
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 2bd3b280e6dd..0b482c0070e0 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -34,6 +34,7 @@
34/* Author: Jakub Kicinski <kubakici@wp.pl> */ 34/* Author: Jakub Kicinski <kubakici@wp.pl> */
35 35
36#include <errno.h> 36#include <errno.h>
37#include <fcntl.h>
37#include <fts.h> 38#include <fts.h>
38#include <libgen.h> 39#include <libgen.h>
39#include <mntent.h> 40#include <mntent.h>
@@ -44,7 +45,9 @@
44#include <unistd.h> 45#include <unistd.h>
45#include <linux/limits.h> 46#include <linux/limits.h>
46#include <linux/magic.h> 47#include <linux/magic.h>
48#include <net/if.h>
47#include <sys/mount.h> 49#include <sys/mount.h>
50#include <sys/stat.h>
48#include <sys/types.h> 51#include <sys/types.h>
49#include <sys/vfs.h> 52#include <sys/vfs.h>
50 53
@@ -163,13 +166,49 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
163 return fd; 166 return fd;
164} 167}
165 168
166int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)) 169int do_pin_fd(int fd, const char *name)
167{ 170{
168 char err_str[ERR_MAX_LEN]; 171 char err_str[ERR_MAX_LEN];
169 unsigned int id;
170 char *endptr;
171 char *file; 172 char *file;
172 char *dir; 173 char *dir;
174 int err = 0;
175
176 err = bpf_obj_pin(fd, name);
177 if (!err)
178 goto out;
179
180 file = malloc(strlen(name) + 1);
181 strcpy(file, name);
182 dir = dirname(file);
183
184 if (errno != EPERM || is_bpffs(dir)) {
185 p_err("can't pin the object (%s): %s", name, strerror(errno));
186 goto out_free;
187 }
188
189 /* Attempt to mount bpffs, then retry pinning. */
190 err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
191 if (!err) {
192 err = bpf_obj_pin(fd, name);
193 if (err)
194 p_err("can't pin the object (%s): %s", name,
195 strerror(errno));
196 } else {
197 err_str[ERR_MAX_LEN - 1] = '\0';
198 p_err("can't mount BPF file system to pin the object (%s): %s",
199 name, err_str);
200 }
201
202out_free:
203 free(file);
204out:
205 return err;
206}
207
208int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
209{
210 unsigned int id;
211 char *endptr;
173 int err; 212 int err;
174 int fd; 213 int fd;
175 214
@@ -195,35 +234,8 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
195 return -1; 234 return -1;
196 } 235 }
197 236
198 err = bpf_obj_pin(fd, *argv); 237 err = do_pin_fd(fd, *argv);
199 if (!err)
200 goto out_close;
201
202 file = malloc(strlen(*argv) + 1);
203 strcpy(file, *argv);
204 dir = dirname(file);
205
206 if (errno != EPERM || is_bpffs(dir)) {
207 p_err("can't pin the object (%s): %s", *argv, strerror(errno));
208 goto out_free;
209 }
210
211 /* Attempt to mount bpffs, then retry pinning. */
212 err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
213 if (!err) {
214 err = bpf_obj_pin(fd, *argv);
215 if (err)
216 p_err("can't pin the object (%s): %s", *argv,
217 strerror(errno));
218 } else {
219 err_str[ERR_MAX_LEN - 1] = '\0';
220 p_err("can't mount BPF file system to pin the object (%s): %s",
221 *argv, err_str);
222 }
223 238
224out_free:
225 free(file);
226out_close:
227 close(fd); 239 close(fd);
228 return err; 240 return err;
229} 241}
@@ -403,3 +415,124 @@ void delete_pinned_obj_table(struct pinned_obj_table *tab)
403 free(obj); 415 free(obj);
404 } 416 }
405} 417}
418
419static char *
420ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
421{
422 struct stat st;
423 int err;
424
425 err = stat("/proc/self/ns/net", &st);
426 if (err) {
427 p_err("Can't stat /proc/self: %s", strerror(errno));
428 return NULL;
429 }
430
431 if (st.st_dev != ns_dev || st.st_ino != ns_ino)
432 return NULL;
433
434 return if_indextoname(ifindex, buf);
435}
436
437static int read_sysfs_hex_int(char *path)
438{
439 char vendor_id_buf[8];
440 int len;
441 int fd;
442
443 fd = open(path, O_RDONLY);
444 if (fd < 0) {
445 p_err("Can't open %s: %s", path, strerror(errno));
446 return -1;
447 }
448
449 len = read(fd, vendor_id_buf, sizeof(vendor_id_buf));
450 close(fd);
451 if (len < 0) {
452 p_err("Can't read %s: %s", path, strerror(errno));
453 return -1;
454 }
455 if (len >= (int)sizeof(vendor_id_buf)) {
456 p_err("Value in %s too long", path);
457 return -1;
458 }
459
460 vendor_id_buf[len] = 0;
461
462 return strtol(vendor_id_buf, NULL, 0);
463}
464
465static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
466{
467 char full_path[64];
468
469 snprintf(full_path, sizeof(full_path), "/sys/class/net/%s/device/%s",
470 devname, entry_name);
471
472 return read_sysfs_hex_int(full_path);
473}
474
475const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino)
476{
477 char devname[IF_NAMESIZE];
478 int vendor_id;
479 int device_id;
480
481 if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
482 p_err("Can't get net device name for ifindex %d: %s", ifindex,
483 strerror(errno));
484 return NULL;
485 }
486
487 vendor_id = read_sysfs_netdev_hex_int(devname, "vendor");
488 if (vendor_id < 0) {
489 p_err("Can't get device vendor id for %s", devname);
490 return NULL;
491 }
492
493 switch (vendor_id) {
494 case 0x19ee:
495 device_id = read_sysfs_netdev_hex_int(devname, "device");
496 if (device_id != 0x4000 &&
497 device_id != 0x6000 &&
498 device_id != 0x6003)
499 p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
500 return "NFP-6xxx";
501 default:
502 p_err("Can't get bfd arch name for device vendor id 0x%04x",
503 vendor_id);
504 return NULL;
505 }
506}
507
508void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
509{
510 char name[IF_NAMESIZE];
511
512 if (!ifindex)
513 return;
514
515 printf(" dev ");
516 if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
517 printf("%s", name);
518 else
519 printf("ifindex %u ns_dev %llu ns_ino %llu",
520 ifindex, ns_dev, ns_inode);
521}
522
523void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
524{
525 char name[IF_NAMESIZE];
526
527 if (!ifindex)
528 return;
529
530 jsonw_name(json_wtr, "dev");
531 jsonw_start_object(json_wtr);
532 jsonw_uint_field(json_wtr, "ifindex", ifindex);
533 jsonw_uint_field(json_wtr, "ns_dev", ns_dev);
534 jsonw_uint_field(json_wtr, "ns_inode", ns_inode);
535 if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
536 jsonw_string_field(json_wtr, "ifname", name);
537 jsonw_end_object(json_wtr);
538}