当前位置:网站首页>龙蜥社区开源 coolbpf,BPF 程序开发效率提升百倍
龙蜥社区开源 coolbpf,BPF 程序开发效率提升百倍
2022-07-01 13:18:00 【InfoQ】
引言
- 系统故障诊断:它可以动态插桩透视内核。
- 网络性能优化:它可以对接收和发送的网络包做修改和转发。
- 系统安全:它可以监控文件打开和关闭从而做出安全决策等。
- 性能监控:它可以查看函数耗费时间从而知道性能瓶颈点。
一、BPF 开发方式对比
1、原始阶段
static struct sock_filter filter[6] = {
{ OP_LDH, 0, 0, 12 }, // ldh [12]
{ OP_JEQ, 0, 2, ETH_P_IP }, // jeq #0x800, L2, L5
{ OP_LDB, 0, 0, 23 }, // ldb [23]
{ OP_JEQ, 0, 1, IPPROTO_TCP }, // jeq #0x6, L4, L5
{ OP_RET, 0, 0, 0 }, // ret #0x0
{ OP_RET, 0, 0, -1, }, // ret #0xffffffff
};
int main(int argc, char **argv)
{
…
struct sock_fprog prog = { 6, filter };
…
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
…
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))) {
return 1;
}
…
}
2、保守阶段
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, long);
__uint(max_entries, 256);
} my_map SEC(".maps");
SEC("socket1")
int bpf_prog1(struct __sk_buff *skb)
{
int index = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));
long *value;
if (skb->pkt_type != PACKET_OUTGOING)
return 0;
value = bpf_map_lookup_elem(&my_map, &index);
if (value)
__sync_fetch_and_add(value, skb->len);
return 0;
}
char _license[] SEC("license") = "GPL";
int main(int ac, char **argv)
{
struct bpf_object *obj;
struct bpf_program *prog;
int map_fd, prog_fd;
char filename[256];
int i, sock, err;
FILE *f;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj))
return 1;
prog = bpf_object__next_program(obj, NULL);
bpf_program__set_type(prog, BPF_PROG_TYPE_SOCKET_FILTER);
err = bpf_object__load(obj);
if (err)
return 1;
prog_fd = bpf_program__fd(prog);
map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
...
}
3、BCC 初始阶段
int trace_connect_v4_entry(struct pt_regs *ctx, struct sock *sk)
{
if (container_should_be_filtered()) {
return 0;
}
u64 pid = bpf_get_current_pid_tgid();
##FILTER_PID##
u16 family = sk->__sk_common.skc_family;
##FILTER_FAMILY##
// stash the sock ptr for lookup on return
connectsock.update(&pid, &sk);
return 0;
}
# initialize BPF
b = BPF(text=bpf_text)
if args.ipv4:
b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_entry")
b.attach_kretprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_return")
b.attach_kprobe(event="tcp_close", fn_name="trace_close_entry")
b.attach_kretprobe(event="inet_csk_accept", fn_name="trace_accept_return")
4、BCC 高级阶段
SEC("kprobe/inet_listen")
int BPF_KPROBE(inet_listen_entry, struct socket *sock, int backlog)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
__u32 pid = pid_tgid >> 32;
__u32 tid = (__u32)pid_tgid;
struct event event = {};
if (target_pid && target_pid != pid)
return 0;
fill_event(&event, sock);
event.pid = pid;
event.backlog = backlog;
bpf_map_update_elem(&values, &tid, &event, BPF_ANY);
return 0;
}
#include "solisten.skel.h"
...
int main(int argc, char **argv)
{
...
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
obj = solisten_bpf__open();
obj->rodata->target_pid = target_pid;
err = solisten_bpf__load(obj);
err = solisten_bpf__attach(obj);
pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES,
handle_event, handle_lost_events, NULL, NULL);
...
}
5、资源共享阶段
- 开箱即用:内核侧仅提供 bpf.c 即可,完全剥离出内核编译工程。
- 复用编译成果:本地侧无编译过程,不存在库依赖和 CPU、内存等资源消耗问题。
- 自适应不同版本差异:更适合在集群多个不同内核版本共存的场景。
先在本地安装coolbpf,里面带的命令会把xx.bpf.c发送到编译服务器编译。
pip install coolbpf
...
import time
from pylcc.lbcBase import ClbcBase
bpfPog = r"""
#include "lbc.h"
SEC("kprobe/wake_up_new_task")
int j_wake_up_new_task(struct pt_regs *ctx)
{
struct task_struct* parent = (struct task_struct *)PT_REGS_PARM1(ctx);
bpf_printk("hello lcc, parent: %d\n", _(parent->tgid));
return 0;
}
char _license[] SEC("license") = "GPL";
"""
class Chello(ClbcBase):
def __init__(self):
super(Chello, self).__init__("hello", bpf_str=bpfPog)
while True:
time.sleep(1)
if __name__ == "__main__":
hello = Chello()
pass
二、coolbpf 功能及架构

1)本地编译服务,基础库封装:客户使用本地容器镜像编译程序,调用封装的通用函数库简化程序编写和数据处理。
2)远程编译服务:接收 bpf.c,生成 bpf.so 或 bpf.o,提供给高级语言进行加载,用户只专注自己的功能开发,不用关心底层库安装、环境搭建。
3)高版本特性通过 kernel module 方式补齐到低版本,如 ring buffer 特性,backport BPF 特性到 3.10 内核。
4)BTF 的自动生成和全网最新内核版本爬虫。自动发现最新的 CentOS、ubuntu、Anolis 等内核版本,自动生成对应的 BTF。
5)各内核版本功能测试自动化,工具编写后自动进行安装测试,保障用户功能在生产环境运行前预测试。
6)Python、Rust、Go、C 等高级语言支持。

三、实践说明
1、pylcc(基于 Python 的 LCC)

bpfPog = r"""
#include "lbc.h"
LBC_PERF_OUTPUT(e_out, struct data_t, 128);
LBC_HASH(pid_cnt, u32, u32, 1024);
LBC_STACK(call_stack,32);
importtimefrompylcc.lbcBaseimportClbcBase
classPingtrace(ClbcBase):def__init__(self):super(Pingtrace, self).__init__("pingtrace")
#include "vmlinux.h"
#include <linux/types.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
2、rlcc(基于 Rust 的 LCC)
编译example流程:
SKEL_RS=1 cargo build --release 生成 rust skel 文件;
SKEL_RS=0 cargo build --release 无需在生成 rust skel 文件;
默认 SKEL_RS 为 1.
编译rexample流程:
rexample 使用了远程编译功能,具体编译流程如下:
运行命令 mkdir build & cd build 创建编译目录;
运行命令 cmake .. 生成 Makefile 文件;
运行命令 make rexample;
运行 example 程序: ../lcc/rlcc/rexample/target/release/rexample.
fn main() -> Result<()>{
let opts = Command::from_args();
let mut skel_builder = ExampleSkelBuilder::default();
if opts.verbose {
skel_builder.obj_builder.debug(true);
}
bump_memlock_rlimit()?;
let mut open_skel = skel_builder.open()?;
let mut skel = open_skel.load()?;
skel.attach()?;
let perf = PerfBufferBuilder::new(skel.maps_mut().events())
.sample_cb(handle_event)
.lost_cb(handle_lost_events)
.build()?;
loop {
perf.poll(Duration::from_millis(100))?;
}
}
3、glcc(generic LCC,高版本特性移植到低版本)
- 目前基于 eBPF 编写的程序只能在高版本内核(支持 eBPF 的内核)上运行,无法在不支持 eBPF 功能的内核上运行。
- 线上有很多 Alios 或者 CentOS 低版本内核需要维护。
- 存量 BPF 工具或项目代码,希望不做修改能跨内核运行。


#define IOCTL_BPF_MAP_CREATE _IOW(';', 0, union bpf_attr *)
#define IOCTL_BPF_MAP_LOOKUP_ELEM _IOWR(';', 1, union bpf_attr *)
#define IOCTL_BPF_MAP_UPDATE_ELEM _IOW(';', 2, union bpf_attr *)
#define IOCTL_BPF_MAP_DELETE_ELEM _IOW(';', 3, union bpf_attr *)
#define IOCTL_BPF_MAP_GET_NEXT_KEY _IOW(';', 4, union bpf_attr *)
#define IOCTL_BPF_PROG_LOAD _IOW(';', 5, union bpf_attr *)
#define IOCTL_BPF_PROG_ATTACH _IOW(';', 6, __u32)
#define IOCTL_BPF_PROG_FUNCNAME _IOW(';', 7, char *)
#define IOCTL_BPF_OBJ_GET_INFO_BY_FD _IOWR(';', 8, union bpf_attr *)
四、总结
边栏推荐
- 股票开户要认识谁?实际上网上开户安全么?
- JS discolored Lego building blocks
- MySQL 66 questions, 20000 words + 50 pictures in detail! Necessary for review
- 9. Use of better scroll and ref
- 啟動solr報錯The stack size specified is too small,Specify at least 328k
- Analysis report on production and marketing demand and investment forecast of global and Chinese diamond powder industry Ⓤ 2022 ~ 2027
- Beidou communication module Beidou GPS module Beidou communication terminal DTU
- Application of 5g industrial gateway in scientific and technological overload control; off-site joint law enforcement for over limit, overweight and overspeed
- 游戏公会在去中心化游戏中的未来
- Use of shutter SQLite
猜你喜欢

The future of game guild in decentralized games

终端识别技术和管理技术

Svg diamond style code
MySQL报错1040Too many connections的原因以及解决方案

Introduction to reverse debugging PE structure input table output table 05/07

Jenkins+webhooks- multi branch parametric construction-

ROS2 Foxy depthai_ ROS tutorial

VM virtual machine configuration dynamic IP and static IP access

1553B environment construction

Google Earth engine (GEE) - Global Human Settlements grid data 1975-1990-2000-2014 (p2016)
随机推荐
Analysis report on the development trend and prospect scale of silicon intermediary industry in the world and China Ⓩ 2022 ~ 2027
Global and Chinese silicone defoamer production and marketing demand and investment forecast analysis report Ⓨ 2022 ~ 2027
SVG钻石样式代码
Three questions about scientific entrepreneurship: timing, pain points and important decisions
软件测试中功能测试流程
nexus搭建npm依赖私库
Development trend and market demand analysis report of China's high purity copper industry Ⓕ 2022 ~ 2028
In the next stage of digital transformation, digital twin manufacturer Youyi technology announced that it had completed a financing of more than 300 million yuan
Idea of [developing killer]
2.15 summary
Declare an abstract class vehicle, which contains the private variable numofwheel and the public functions vehicle (int), horn (), setnumofwheel (int) and getnumofwheel (). Subclass mot
Router. use() requires a middleware function but got a Object
[development of large e-commerce projects] performance pressure test - basic concept of pressure test & jmeter-38
Function test process in software testing
C language learning
Apache-atlas-2.2.0 independent compilation and deployment
商汤科技崩盘 :IPO时已写好的剧本
CV顶会最佳论文得主分享:好论文是怎么炼成的?
Report on the "14th five year plan" and investment strategy recommendations for China's industrial robot industry 2022 ~ 2028
股票开户要认识谁?实际上网上开户安全么?