ebfp编程常用API介绍

目录

1 用户态API

1.1 加载prog

1.2 查询prog的信息

1.3 prog绑定到固定的dev上

1.4 创建MAP

1.5 查询MAP

1.6 Object Pinning(钉住对象)

2 内核态API

2.1 内核总体API

2.2 bpf 加载

2.2.1 prog 加载

2.3 bpf map 操作

2.3.1 map 创建

2.3.2 map 查找

2.3.3 BPF_FUNC_map_lookup_elem

2.4 obj pin(盯住对象)

 2.4.1 bpf_obj_do_pin

 2.4.2 bpf_obj_get


1 用户态API

1.1 加载prog

static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
{
int fd;

do {
fd = sys_bpf(BPF_PROG_LOAD, attr, size);
} while (fd < 0 && errno == EAGAIN);

return fd;
}

1.2 查询prog的信息

int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len)
{
union bpf_attr attr;
int err;

memset(&attr, 0, sizeof(attr));
attr.info.bpf_fd = prog_fd;
attr.info.info_len = *info_len;
attr.info.info = ptr_to_u64(info);

err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
if (!err)
*info_len = attr.info.info_len;

return err;
}

1.3 prog绑定到固定的dev上

使用的是netlink消息跟内核通信,把fd和dev信息以及flag发送到内核,netlink使用的是NETLINK_ROUTE

int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
{
int sock, seq = 0, ret;
struct nlattr *nla, *nla_xdp;
struct {
struct nlmsghdr nh;
struct ifinfomsg ifinfo;
char attrbuf[64];
} req;
__u32 nl_pid;

sock = libbpf_netlink_open(&nl_pid);
if (sock < 0)
return sock;

memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_type = RTM_SETLINK;
req.nh.nlmsg_pid = 0;
req.nh.nlmsg_seq = ++seq;
req.ifinfo.ifi_family = AF_UNSPEC;
req.ifinfo.ifi_index = ifindex;

/* started nested attribute for XDP */
nla = (struct nlattr *)(((char *)&req)
+ NLMSG_ALIGN(req.nh.nlmsg_len));
nla->nla_type = NLA_F_NESTED | IFLA_XDP;
nla->nla_len = NLA_HDRLEN;

/* add XDP fd */
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = IFLA_XDP_FD;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
nla->nla_len += nla_xdp->nla_len;

/* if user passed in any flags, add those too */
if (flags) {
nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
nla_xdp->nla_type = IFLA_XDP_FLAGS;
nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
nla->nla_len += nla_xdp->nla_len;
}

req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);

if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
ret = -errno;
goto cleanup;
}
ret = bpf_netlink_recv(sock, nl_pid, seq, NULL, NULL, NULL);

cleanup:
close(sock);
return ret;
}

1.4 创建MAP

int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
{
union bpf_attr attr;

memset(&attr, '\0', sizeof(attr));

attr.map_type = create_attr->map_type;
attr.key_size = create_attr->key_size;
attr.value_size = create_attr->value_size;
attr.max_entries = create_attr->max_entries;
attr.map_flags = create_attr->map_flags;
if (create_attr->name)
memcpy(attr.map_name, create_attr->name,
min(strlen(create_attr->name), BPF_OBJ_NAME_LEN - 1));
attr.numa_node = create_attr->numa_node;
attr.btf_fd = create_attr->btf_fd;
attr.btf_key_type_id = create_attr->btf_key_type_id;
attr.btf_value_type_id = create_attr->btf_value_type_id;
attr.map_ifindex = create_attr->map_ifindex;
attr.inner_map_fd = create_attr->inner_map_fd;

return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
}

1.5 查询MAP


int bpf_map_lookup_elem(int fd, const void *key, void *value)
{
union bpf_attr attr;

memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = ptr_to_u64(key);
attr.value = ptr_to_u64(value);

return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}

1.6 Object Pinning(钉住对象)

int bpf_obj_pin(int fd, const char *pathname)
{
union bpf_attr attr;

memset(&attr, 0, sizeof(attr));
attr.pathname = ptr_to_u64((void *)pathname);
attr.bpf_fd = fd;

return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
}

int bpf_obj_get(const char *pathname)
{
union bpf_attr attr;

memset(&attr, 0, sizeof(attr));
attr.pathname = ptr_to_u64((void *)pathname);

return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
}

目前支持的CMD类型

/* BPF syscall commands, see bpf(2) man-page for details. */
enum bpf_cmd {
    BPF_MAP_CREATE,
    BPF_MAP_LOOKUP_ELEM,
    BPF_MAP_UPDATE_ELEM,
    BPF_MAP_DELETE_ELEM,
    BPF_MAP_GET_NEXT_KEY,
    BPF_PROG_LOAD,
    BPF_OBJ_PIN,
    BPF_OBJ_GET,
    BPF_PROG_ATTACH,
    BPF_PROG_DETACH,
    BPF_PROG_TEST_RUN,
    BPF_PROG_GET_NEXT_ID,
    BPF_MAP_GET_NEXT_ID,
    BPF_PROG_GET_FD_BY_ID,
    BPF_MAP_GET_FD_BY_ID,
    BPF_OBJ_GET_INFO_BY_FD,
    BPF_PROG_QUERY,
    BPF_RAW_TRACEPOINT_OPEN,
    BPF_BTF_LOAD,
    BPF_BTF_GET_FD_BY_ID,
    BPF_TASK_FD_QUERY,
};

2 内核态API

2.1 内核总体API

kernel/bpf/syscall.c
 
SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
{
    union bpf_attr attr;
    int err;
    if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN))
        return -EPERM;
    err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);
    if (err)
        return err;
    size = min_t(u32, size, sizeof(attr));
    /* copy attributes from user space, may be less than sizeof(bpf_attr) */
    memset(&attr, 0, sizeof(attr));
    if (copy_from_user(&attr, uattr, size) != 0)
        return -EFAULT;
    err = security_bpf(cmd, &attr, size);
    if (err < 0)
        return err;
    switch (cmd) {
    case BPF_MAP_CREATE:
        err = map_create(&attr);
        break;
    case BPF_MAP_LOOKUP_ELEM:
        err = map_lookup_elem(&attr);
        break;
    case BPF_MAP_UPDATE_ELEM:
        err = map_update_elem(&attr);
        break;
    case BPF_MAP_DELETE_ELEM:
        err = map_delete_elem(&attr);
        break;
    case BPF_MAP_GET_NEXT_KEY:
        err = map_get_next_key(&attr);
        break;
    case BPF_PROG_LOAD:
        err = bpf_prog_load(&attr);
        break;
    case BPF_OBJ_PIN:
        err = bpf_obj_pin(&attr);
        break;
    case BPF_OBJ_GET:
        err = bpf_obj_get(&attr);
        break;
    case BPF_PROG_ATTACH:
        err = bpf_prog_attach(&attr);
        break;
    case BPF_PROG_DETACH:
        err = bpf_prog_detach(&attr);
        break;
    case BPF_PROG_QUERY:
        err = bpf_prog_query(&attr, uattr);
        break;
    case BPF_PROG_TEST_RUN:
        err = bpf_prog_test_run(&attr, uattr);
        break;
    case BPF_PROG_GET_NEXT_ID:
        err = bpf_obj_get_next_id(&attr, uattr,
                      &prog_idr, &prog_idr_lock);
        break;
    case BPF_MAP_GET_NEXT_ID:
        err = bpf_obj_get_next_id(&attr, uattr,
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值