0
点赞
收藏
分享

微信扫一扫

创建BPF映射方式

菜头粿子园 2022-02-09 阅读 73

💡 BPF映射如何创建

程序员经常向程序传递消息引起程序行为被调用。bpf 最神奇的功能就是内核中运行的代码,和加载这些代码的程序可以通过消息传递方式实现实时通信。

BPF 映射是键值保存在内核中,可以被 BPF 程序访问。用户空间的程序也可以通过文件描述符访问 bpf 映射。bpf 映射中可以保存事先指定的大小任何类型数据。

内核将键值作为二进制块,内核并不关系 bpf 映射的具体内容,由验证器来保证安全。

创建 BPF 映射

创建 BPF 映射最直接的方法是使用 bpf 系统调用,第一个参数设置为 BPF_MAP_CREATE,则表示创建一个新的映射。

该调用将返回与创建映射相关的文件描述符。bpf 系统调用的第二个参数如下所示:

https://man7.org/linux/man-pages/man2/bpf.2.htm[1]

BPF_PROG_LOAD
              Verify and load an eBPF program, returning a new file
              descriptor associated with the program.  The close-on-exec
              file descriptor flag (seefcntl(2)) is automatically
              enabled for the new file descriptor.

              Thebpf_attr union consists of various anonymous
              structures that are used by differentbpf() commands:

           union bpf_attr {
               struct {    /* Used by BPF_MAP_CREATE */
                   __u32         map_type;
                   __u32         key_size;    /* size of key in bytes */
                   __u32         value_size;  /* size of value in bytes */
                   __u32         max_entries; /* maximum number of entries
                                                 in a map */
               };

               struct {    /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY
                              commands */
                   __u32         map_fd;
                   __aligned_u64 key;
                   union {
                       __aligned_u64 value;
                       __aligned_u64 next_key;
                   };
                   __u64         flags;
               };

               struct {    /* Used by BPF_PROG_LOAD */
                   __u32         prog_type;
                   __u32         insn_cnt;
                   __aligned_u64 insns;      /* 'const struct bpf_insn *' */
                   __aligned_u64 license;    /* 'const char *' */
                   __u32         log_level;  /* verbosity level of verifier */
                   __u32         log_size;   /* size of user buffer */
                   __aligned_u64 log_buf;    /* user supplied 'char *'
                                                buffer */
                   __u32         kern_version;
                                             /* checked when prog_type=kprobe
                                                (since Linux 4.1) */
               };
           } __attribute__((aligned(8)));

如果系统调用失败,内核返回-1;失败的原因主要有三种:属性无效 EINVAL,没有足够的执行权限 EPERM,没有足够的内存保存映射 ENOMEM。

使用 ELF 约定创建 BPF 映射

内核中包括一些约定和帮助函数,用于生成和使用 BPF 映射。

如帮助函数bpf_create_map封装了上面的代码。

可以预先定义映射:

struct bpf_map_def SEC("maps") my_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size= sizeof(int),
    .value_size=sizeof(int),
    .max_entries=100,
    .map_flags = BPF_F_NO_PREALLOC,
};

这种方式使用section属性来定义映射,本示例中为SEC(“maps”)。告诉内核结构时 bpf 映射,并告诉内核创建相应的映射。

映射初始化后,就可以使用他们在内核和用户空间之间传递消息。

#include <errno.h>
#include <linux/bpf.h>
#include <stdio.h>
#include <string.h>
#include "bpf.h"

static const char *file_path = "/sys/fs/bpf/my_array";

int main(int argc, char **argv) {
  int key, value, fd, added, pinned;

  fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(int), 100, 0);
  if (fd < 0) {
    printf("Failed to create map: %d (%s)\n", fd, strerror(errno));
    return -1;
  }

  key = 1, value = 1234;
  added = bpf_map_update_elem(fd, &key, &value, BPF_ANY);
  if (added < 0) {
    printf("Failed to update map: %d (%s)\n", added, strerror(errno));
    return -1;
  }

  pinned = bpf_obj_pin(fd, file_path);
  if (pinned < 0) {
    printf("Failed to pin map to the file system: %d (%s)\n", pinned,
           strerror(errno));
    return -1;
  }

  return 0;
}

💡 小贴士:calico:Here’s @TomkinsDA 's #FOSDEM 2022 talk titled ‘2-cluster #Kubernetes, with #Calico, #BGP Interconnect and #WireGuard… All Without Leaving Your Laptop!’… Stay tuned for the fun surprise at the end.

https://video.fosdem.org/2022/D.network/2_cluster_kubernetes_with_calico_bgp_interconnect_and_wireguard_all_without_leaving_your_laptop.webm[2]

参考资料

[1]

https://man7.org/linux/man-pages/man2/bpf.2.htm: https://man7.org/linux/man-pages/man2/bpf.2.htm

[2]

https://video.fosdem.org/2022/D.network/2_cluster_kubernetes_with_calico_bgp_interconnect_and_wireguard_all_without_leaving_your_laptop.webm: https://man7.org/linux/man-pages/man2/bpf.2.htm

举报

相关推荐

0 条评论