×
Community Blog Use Coolbpf’s LWCB and Forget Dependence on Clang

Use Coolbpf’s LWCB and Forget Dependence on Clang

This article introduces the Coolbpf project’s new lightweight scripting programming feature: Lightweight Coolbpf (LWCB).

1

By eBPF Research SIG

The Coolbpf project based on CO-RE (Compile Once - Run Everywhere) introduces a new lightweight scripting programming feature called Lightweight Coolbpf (LWCB). LWCB is a scripting language and tracing development tool for eBPF. It can parse scripts written by users and generate eBPF bytecode to realize trace diagnosis, performance analysis, and monitoring of a Linux kernel system. In addition, LWCB provides a large number of built-in functions. For example, tcpstate can easily convert integers into tcp state strings, and tcphdr and iphdr can allow users to obtain tcphdr or iphdr structures from skb to quickly write eBPF programs related to kernel networks. LWCB allows users to easily add more built-in functions to cover more application scenarios.

LWCB Features

Lightweight and Easy to Deploy

LWCB uses Rust to develop a small parser that does not rely on Clang. It uses a lightweight compiler and adds an eBPF backend to the compiler, so it does not need to rely on llvm. After LWCB is compiled, there is only one independent binary program with a size of about 8MB, so it is convenient and fast to deploy. Previously, a bunch of compilation and runtime libraries were needed to install on the target execution machine to deploy tools (such as BCC and bpftrace).

Scripted and Fast to Develop

Currently, LWCB supports script interpretation execution capabilities similar to bpftrace. It beats bpftrace with the advantage that no compilation is required, and it provides more built-in functions to facilitate development and use. In addition, it naturally supports CO-RE to run safely on different kernel versions. Tts functions are more powerful.

The strong functionality of LWCB is mainly reflected in the following points:

1.  Have More Built-In Functions: Such as tcphdr, iphdr, and tcpstate

2.  Allow Automatic Parameters Injection of Probe Point Function

lwcb -t 'kprobe:tcp_rcv_established { ih = iphdr(skb); print("sip: %s dip: %s\n", ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr))); }'

You can directly access the skb parameter of the tcp_rcv_established function to obtain IP addresses and port numbers.

3.  Support BTF: It can carry on type deduction. For example, th = tcphdr(skb), LWCB can know from the BTF information that the type of skb is struct sk_buff* and the type of this struct tcphdr *. Users can directly access the members of the struct tcphdr structure (such as th->source) without declaring the type of th.

4.  Support Python: This function allows LWCB to make full use of Python for complex data processing. It is similar to the development method of bcc. You can use the function by importing Pylwcb. Here is a simple example:

import pylwcb
lwcb_program = """
    kprobe:tcp_rcv_established {
        th = tcphdr(skb);
        ih = iphdr(skb);
        print(ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr)), bswap(th->source), bswap(th->dest));
    }
    """
lwcb = pylwcb.Pylwcb(lwcb_program)
lwcb.attach()
events = lwcb.read_events()
for event in events:
    print(event)

5.  Support Batch Probe Points: kprobe:(struct sock *sk) tracks all functions with struct sock *sk parameters in the kernel. You can use this feature to implement finer-grained function graphs.

kprobe:(struct sock *sk) {
  sport = sk->__sk_common.skc_num;
  if (sport == 22) {
    print("%s %s\n", timestr(ns()), ksym(reg("ip")));
  }
}

LWCB Usage

Update Coolbpf to version 1.0.0 to use LWCB scripted programming features.

Compile LWCB

1.  Prepare the compilation environment.

Install the Rust compilation toolchain: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh and clone Coolbpf code: git clone https://gitee.com/anolis/coolbpf.git to enter the LWCB directory: cd coolbpf/lwcb.

2.  Compile: Run cargo build --release to complete the compilation, and the generated LWCB executable program is in: target/release/lwcb.

3.  In addition, LWCB needs BTF files to run. You can download the BTF files of the corresponding kernel from this website and put them in the /boot directory.

LWCB Runs Single-Line Command

lwcb -t <TEXT> can directly run an eBPF program in the form of a single command, such as:

lwcb -t 'kprobe:tcp_rcv_established {print("%s :triggerred by tcp_rcv_established\n", timestr(ns()));}

LWCB Executing Scripts

lwcb <*.cb> directly executes scripts. There are several LWCB scripts in the coolbpf/tools/lwcb directory. You can run the lwcb tcpdrop.cb command to execute the tcpdrop script.

Pylwcb: Python Module of LWCB

Pylwcb is a Python module of LWCB. Through Pylwcb, you can use the scripting capabilities provided by LWCB and take advantage of Python's powerful data processing capabilities.

Pylwcb Usage

Compile Pylwcb

1. Prepare the Compilation Environment

  1. Go to the Pylwcb project directory: cd coolbpf/lwcb/pylwcb
  2. Create a separate Python virtual environment: python -m venv .env
  3. Activate the development virtual environment: source .env/bin/activate
  4. Install the Python library that the Pylwcb compilation environment depends on: pip install tomli && pip install setuptools_rust && pip install maturin

2. Compile Pylwcb

You can run the maturin develop command to compile Pylwcb to produce the corresponding Python module. Generally, the directory where the generated Python module is located is: .env/lib64/python3.6/site-packages/.

Use Pylwcb

Here is an example of a simple Pylwcb script:

import pylwcb
lwcb_program = """
kprobe:tcp_rcv_established {
    th = tcphdr(skb);
    ih = iphdr(skb);
    print(ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr)), bswap(th->source), bswap(th->dest));
}
"""
lwcb = pylwcb.Pylwcb(lwcb_program)
lwcb.attach()
events = lwcb.read_events()
for event in events:
print(event)
  • lwcb_program stores the LWCB script code. Its main function is to probe the tcp_rcv_established function of a kernel and print the four tuples of tcp received packets, namely, source address, destination address, source port, and destination port.
  • lwcb=pylwcb.Pylwcb (lwcb_program) creates a Pylwcb instance
  • lwcb.attach() compiles and loads the eBPF program
  • lwcb.read_events() reads the output of the eBPF program

Related Links

0 0 0
Share on

OpenAnolis

83 posts | 5 followers

You may also like

Comments