[转帖]Linux性能优化(四)——BCC性能监控工具

linux,性能,优化,bcc,监控,工具 · 浏览次数 : 0

小编点评

This Python code implements a custom XDP function `xdp_prog1` for a network device. Here's a summary of its functionality: **Purpose:** - It counts the number of received packets and measures the elapsed time between consecutive received packets. - It determines if the received packets exceed a maximum number allowed (MAX_NB_PACKETS). - It parses double and single-precision IPv4 and IPv6 addresses from the received data. - It drops packets based on the received protocol and the detected DOS flag. - It prints the number of received packets per IP protocol encountered and stops the program when the user presses Ctrl+C. **Functionality Details:** 1. **Counting and Timestamping:** - It maintains two variables, `rcv_packets_nb_ptr` and `rcv_packets_ts_ptr`, to keep track of the current received packet counter and timestamp, respectively. - It uses the `lookup` method to retrieve the current positions of the `rcv_packets_nb_ptr` and `rcv_packets_ts_ptr` in the `rcv_packets` table. 2. **Protocol and Address Extraction:** - It extracts the high-order 8 bits from the `h_proto` variable to determine the protocol type (e.g., 802.1Q or 802.1AD). - It parses double and single-precision IPv4 and IPv6 addresses from the data and stores them in the `index` variable. 3. **Drop Handling:** - It checks the `index` to determine if the packet should be dropped based on the protocol type and the detected DOS flag. - If the packet count exceeds the allowed maximum (MAX_NB_PACKETS), it sets `ret` to 1 and returns an error. 4. **Printing Drops:** - It retrieves the count of dropped packets for each IP protocol encountered and prints the number of packets received per protocol. 5. **Cleanup:** - It removes the filter from the device and cleans up the `dropcnt` table and any associated data. **Overall, this code provides a custom XDP function that monitors and drops incoming network packets based on their protocol and address, while providing information about dropped packets.**

正文

 

 

1、BCC简介

一、BCC简介

BCC是一个Python库,简化了eBPF应用的开发过程,并收集了大量性能分析相关的eBPF应用。BCC为BPF开发提供了不一样的前端支持,包括Python和Lua,实现了map建立、代码编译、解析、注入等操做,使开发人员只需聚焦于用C语言开发要注入的内核代码。
BCC工具集大部分工具须要Linux Kernel 4.1以上版本支持,完整工具支持须要Linux Kernel 4.15以上版本支持。
GitHub:https://github.com/iovisor/bcc前端

二、BCC安装

yum install bcc-tools
export PATH=$PATH:/usr/share/bcc/tools

2、经常使用命令工具

一、opensnoop

opensnoop经过追踪open()系统调用显示企图打开文件的进程,能够用于定位配置文件或日志文件,或排除启动失败的故障应用。
opensnoop经过动态追踪sys_open()内核函数并更新函数的任何变化,opensnoop须要Linux Kernel 4.5版本支持,因为使用BPF,所以须要root权限。
opensnoop [-h] [-T] [-U] [-x] [-p PID] [-t TID] [-u UID] [-d DURATION] [-n NAME] [-e] [-f FLAG_FILTER]
-h, --help:帮助信息查看
-T, --timestamp:输出结果打印时间戳
-U, --print-uid:打印UID
-x, --failed:只显示失败open系统调用
-p PID, --pid PID:只追踪PID进程
-t TID, --tid TID:只追踪TID线程
-u UID, --uid UID:只追踪UID
-d DURATION, --duration DURATION:追踪时间,单位为秒
-n NAME, --name NAME:只打印包含name的进程
-e, --extended_fields:显示扩展字段
-f FLAG_FILTER, --flag_filter FLAG_FILTER:指定过滤字段,如O_WRONLYpython

二、execsnoop

execsnoop经过追踪exec系统调用追踪新进程,对于使用fork而不是exec产生的进程不会包括在显示结果中。
execsnoop须要BPF支持,所以须要root权限。
execsnoop [-h] [-T] [-t] [-x] [-q] [-n NAME] [-l LINE] [--max-args MAX_ARGS]
-h:查看帮助信息
-T:打印时间戳,格式HH:MM:SS
-t:打印时间戳
-x:包括失败exec
-n NAME:只打印正则表达式匹配name的命令行
-l LINE:只打印参数中匹配LINE的命令行
--max-args MAXARGS:解析和显示最大参数数量,默认为20个linux

三、biolatency

biolatency经过追踪块设备IO,记录IO延迟分布,并以直方图显示。biolatency经过动态追踪blk_族函数并记录函数的变化。
biolatency须要BPF支持,所以须要root权限。
biolatency [-h] [-F] [-T] [-Q] [-m] [-D] [interval [count]]
-h Print usage message.
-T:输出包含时间戳
-m:输出ms级直方图
-D:打印每一个磁盘设备的直方图
-F:打印每一个IO集的直方图
interval:输出间隔
count:输出数量
Linux性能优化(四)——BCC性能监控工具ios

四、ext4slower

ext4slower经过跟踪ext4文件系统的read、write、open、sync操做,并测量相应操做所耗时间,打印超过阈值的详细信息。默认阈值最小值是10ms,若是阈值为0,则打印全部事件。
ext4slower须要BPF支持,所以须要root权限。
ext4slower能够经过文件系统识别独立较慢的磁盘IO。
ext4slower [-h] [-j] [-p PID] [min_ms]
-h, --help:查看帮助信息
-j, --csv:使用csv格式打印字段
-p PID, --pid PID:只追踪PID进程
min_ms:追踪IO的阈值,默认为10。
Linux性能优化(四)——BCC性能监控工具git

五、biosnoop

biosnoop能够追踪设备IO并为每一个IO设备打印一行汇总信息。
biosnoop经过动态追踪blk_族函数并记录函数的变化。
biosnoop须要BPF支持,所以须要root权限。
biosnoop [-hQ]
-h:查看帮助信息
-Q:显示在OS队列的耗时
Linux性能优化(四)——BCC性能监控工具github

六、cachestat

cachestat用于统计Linux Page的命中率和缺失率,经过动态追踪内核页的cache函数,并更新cache函数的任何变化。
cachestat须要BPF支持,所以须要root权限。
cachestat [-h] [-T] [interval] [count]
-h:查看帮助信息
-T, --timestamp:输出时间戳
interval:输出间隔,单位为秒
count:输出数量
Linux性能优化(四)——BCC性能监控工具正则表达式

七、cachetop

cachetop用于统计每一个进程的Linux Page缓存的命中率和缺失率,经过动态追踪内核页的cache函数,并更新cache函数的任何变化。
cachestat须要BPF支持,所以须要root权限。
cachetop [-h] [interval]
-h:查看帮助信息
interval:输出间隔
Linux性能优化(四)——BCC性能监控工具
PID:进程ID
UID:进程用户ID
HITS:页缓存命中数量
MISSES:页缓存缺失数量
DIRTIES:增长到页缓存的脏页数量
READ_HIT%:页缓存的读命中率
WRITE_HIT%:页缓存的写命中率
BUFFERS_MB:Buffer大小,数据源/proc/meminfo
CACHED_MB:当前页的Cache大小,数据源/proc/meminfo编程

八、tcpconnect

tcpconnect用于追踪TCP活跃链接数量,经过动态追踪内核tcp_v4_connect和tcp_v6_connect函数,并记录函数内的任何变化。
tcpconnect须要BPF支持,所以须要root权限。
tcpconnect [-h] [-c] [-t] [-x] [-p PID] [-P PORT]
-h:查看帮助信息
-t:打印时间戳
-c:统计每一个源IP和目的IP/端口的链接数
-p PID:只追踪PID进程
-P PORT:要追踪的目的端口列表,使用逗号分隔
Linux性能优化(四)——BCC性能监控工具api

九、trace

trace用于追踪某个函数调用并打印函数参数或返回值,须要BPF支持,所以须要root权限。
trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [-v] [-Z STRING_SIZE] [-S] [-s SYM_FILE_LIST] [-M MAX_EVENTS] [-t] [-u] [-T] [-C] [-K] [-U] [-a] [-I header] probe [probe ...]
-h:查看帮助信息
-p PID:只追踪PID进程
-L TID:只追踪TID线程
-v:显示生成的BPF程序,调试使用
-z STRING_SIZE:收集字符串参数的长度
-s SYM_FILE_LIST:收集栈大小
-M MAX_EVENTS:打印追踪消息的最大数量
-t:打印时间,单位为秒。
-u:打印时间戳
-T:打印时间列
-C:打印CPU ID
-K:打印每一个事件的内核栈
-U:打印每一个事件的用户栈
-a:打印序内核栈和用户栈的虚拟地址
-I header:增长header文件到BPF程序
probe [probe ...]:附加到函数的探针
trace '::do_sys_open "%s", arg2'
追踪open系统调用的全部调用方式
Linux性能优化(四)——BCC性能监控工具
trace ':c:malloc "size = %d", arg1'
追踪malloc调用并打印申请分配内存的大小
Linux性能优化(四)——BCC性能监控工具
trace 'u:pthread:pthread_create "start addr = %llx", arg3'
追踪pthread_create函数调用并打印线程启动函数地址
Linux性能优化(四)——BCC性能监控工具缓存

十、deadlock

deadlock用于查找正在运行进程潜在的死锁。deadlock经过附加uprobe事件,须要BPF支持,所以须要root权限。
deadlock [-h] [--binary BINARY] [--dump-graph DUMP_GRAPH] [--verbose] [--lock-symbols LOCK_SYMBOLS] [--unlock-symbols UNLOCK_SYMBOLS] pid
-h, --help:查看帮助信息
--binary BINARY:指定线程库,对于动态连接程序必须指定。
--dump-graph DUMP_GRAPH:导出mutex图到指定文件
--verbose:打印mutex统计信息
--lock-symbols LOCK_SYMBOLS:要追踪的锁的列表,使用逗号分隔,默认为pthread_mutex_lock。
--unlock-symbols UNLOCK_SYMBOLS:要追踪的解锁的列表,使用逗号分隔,默认为pthread_mutex_unlock。
pid:要追踪的进程ID
deadlock 181 --binary /lib/x86_64-linux-gnu/libpthread.so.0
查找进程181中的潜在死锁,若是进程被动态连接程序建立,须要使用--binary指定使用的线程库。

十一、memleak

memleak用于追踪和查找内存分配和释放配对,须要Linux Kernel 4.7以上版本支持。
memleak [-h] [-p PID] [-t] [-a] [-o OLDER] [-c COMMAND] [--combined-only] [-s SAMPLE_RATE] [-T TOP] [-z MIN_SIZE] [-Z MAX_SIZE] [-O OBJ] [INTERVAL] [COUNT]
-h:查看帮助信息
-p PID:指定进程PID
-t:追踪全部内存分配和释放请求和结果
-a:输出未释放内存的列表
-z MIN_SIZE:捕获分配内存的最小值
-Z MAX_SIZE:捕获分配内存的最大值
memleak -z 16 -Z 32
只捕获分析分配大小未16字节至32字节间的内存分配

3、BCC编程开发

一、BCC实现原理

BCC是eBPF的一个工具集,是对eBPF提取数据的上层封装,BCC工具编程形式是Python中嵌套BPF程序。Python代码能够为用户提供友好使用eBPF的上层接口,也能够用于数据处理。BPF程序会注入内核,提取数据。当BPF程序运行时,经过LLVM将BPF程序编译获得BPF指令集的elf文件,从elf文件中解析出能够注入内核的部分,使用bpf_load_program方法完成注入。
bpf_load_program注入程序方法加入了复杂的verifier机制,在运行注入程序前,先进行一系列的安全检查,最大限度的保证系统的安全。通过安全检查的BPF字节码使用内核JIT进行编译,生成本机汇编指令,附加到内核特定挂钩的程序。最终内核态与用户态经过高效的map机制进行通讯,BCC工具在用户态使用Python进行数据处理。
Linux性能优化(四)——BCC性能监控工具

二、BCC示例实现

Python部分编码须要引入使用的模块和包。
BCC工具的Python部分代码中经过以下方式使用BPF C语言程序代码:
hello_world.py:

#!/usr/bin/python3
from bcc import BPF
bpf_program = '''
int kprobe__sys_clone(void *ctx) 
{ 
    bpf_trace_printk("Hello, World!\\n");
    return 0;
}'''
if __name__ == "__main__":
       BPF(text=bpf_program).trace_print()

kprobe__sys_clone是经过kprobes进行内核动态跟踪的快捷方式,若是C函数以开头kprobe__,则其他部分被视为要检测的内核函数名称。
bpf_trace_printk: 输出
python3 hello_world.py
Linux性能优化(四)——BCC性能监控工具

三、DDOS防护示例

#!/usr/bin/python
from bcc import BPF
import pyroute2
import time
import sys

flags = 0
def usage():
    print("Usage: {0} [-S] <ifdev>".format(sys.argv[0]))
    print("       -S: use skb mode\n")
    print("e.g.: {0} eth0\n".format(sys.argv[0]))
    exit(1)

if len(sys.argv) < 2 or len(sys.argv) > 3:
    usage()

if len(sys.argv) == 2:
    device = sys.argv[1]

if len(sys.argv) == 3:
    if "-S" in sys.argv:
        # XDP_FLAGS_SKB_MODE
        flags |= 2 << 0

    if "-S" == sys.argv[1]:
        device = sys.argv[2]
    else:
        device = sys.argv[1]

mode = BPF.XDP
ctxtype = "xdp_md"

# load BPF program
b = BPF(text = """
#define KBUILD_MODNAME "foo"
#include <uapi/linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>

// how to determin ddos
#define MAX_NB_PACKETS 1000
#define LEGAL_DIFF_TIMESTAMP_PACKETS 1000000

// store data, data can be accessd in kernel and user namespace
BPF_HASH(rcv_packets);
BPF_TABLE("percpu_array", uint32_t, long, dropcnt, 256);

static inline int parse_ipv4(void *data, u64 nh_off, void *data_end) {
    struct iphdr *iph = data + nh_off;
    if ((void*)&iph[1] > data_end)
        return 0;
    return iph->protocol;
}
static inline int parse_ipv6(void *data, u64 nh_off, void *data_end) {
    struct ipv6hdr *ip6h = data + nh_off;
    if ((void*)&ip6h[1] > data_end)
        return 0;
    return ip6h->nexthdr;
}

// determine ddos
static inline int detect_ddos(){
    // Used to count number of received packets
    u64 rcv_packets_nb_index = 0, rcv_packets_nb_inter=1, *rcv_packets_nb_ptr;
    // Used to measure elapsed time between 2 successive received packets
    u64 rcv_packets_ts_index = 1, rcv_packets_ts_inter=0, *rcv_packets_ts_ptr;
    int ret = 0;

    rcv_packets_nb_ptr = rcv_packets.lookup(&rcv_packets_nb_index);
    rcv_packets_ts_ptr = rcv_packets.lookup(&rcv_packets_ts_index);
    if(rcv_packets_nb_ptr != 0 && rcv_packets_ts_ptr != 0){
        rcv_packets_nb_inter = *rcv_packets_nb_ptr;
        rcv_packets_ts_inter = bpf_ktime_get_ns() - *rcv_packets_ts_ptr;
        if(rcv_packets_ts_inter < LEGAL_DIFF_TIMESTAMP_PACKETS){
            rcv_packets_nb_inter++;
        } else {
            rcv_packets_nb_inter = 0;
        }
        if(rcv_packets_nb_inter > MAX_NB_PACKETS){
            ret = 1;
        }
    }
    rcv_packets_ts_inter = bpf_ktime_get_ns();
    rcv_packets.update(&rcv_packets_nb_index, &rcv_packets_nb_inter);
    rcv_packets.update(&rcv_packets_ts_index, &rcv_packets_ts_inter);
    return ret;
}

// determine and recode by proto
int xdp_prog1(struct CTXTYPE *ctx) {
    void* data_end = (void*)(long)ctx->data_end;
    void* data = (void*)(long)ctx->data;
    struct ethhdr *eth = data;
    // drop packets
    int rc = XDP_PASS; // let pass XDP_PASS or redirect to tx via XDP_TX
    long *value;
    uint16_t h_proto;
    uint64_t nh_off = 0;
    uint32_t index;
    nh_off = sizeof(*eth);
    if (data + nh_off  > data_end)
        return rc;
    h_proto = eth->h_proto;
    // parse double vlans
    if (detect_ddos() == 0){
        return rc;
    }
    rc = XDP_DROP;
    #pragma unroll
    for (int i=0; i<2; i++) {
        if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
            struct vlan_hdr *vhdr;
            vhdr = data + nh_off;
            nh_off += sizeof(struct vlan_hdr);
            if (data + nh_off > data_end)
                return rc;
                h_proto = vhdr->h_vlan_encapsulated_proto;
        }
    }
    if (h_proto == htons(ETH_P_IP))
        index = parse_ipv4(data, nh_off, data_end);
    else if (h_proto == htons(ETH_P_IPV6))
       index = parse_ipv6(data, nh_off, data_end);
    else
        index = 0;
    value = dropcnt.lookup(&index);
    if (value)
        *value += 1;
    return rc;
}
""", cflags=["-w", "-DCTXTYPE=%s" % ctxtype])

fn = b.load_func("xdp_prog1", mode)
b.attach_xdp(device, fn, flags)

dropcnt = b.get_table("dropcnt")
prev = [0] * 256
print("Printing drops per IP protocol-number, hit CTRL+C to stop")
while 1:
    try:
        for k in dropcnt.keys():
            val = dropcnt.sum(k).value
            i = k.value
            if val:
                delta = val - prev[i]
                prev[i] = val
                print("{}: {} pkt/s".format(i, delta))
        time.sleep(1)
    except KeyboardInterrupt:
        print("Removing filter from device")
        break;

b.remove_xdp(device, flags)

与[转帖]Linux性能优化(四)——BCC性能监控工具相似的内容:

[转帖]Linux性能优化(四)——BCC性能监控工具

一、BCC简介 1、BCC简介 BCC是一个Python库,简化了eBPF应用的开发过程,并收集了大量性能分析相关的eBPF应用。BCC为BPF开发提供了不同的前端支持,包括Python和Lua,实现了map创建、代码编译、解析、注入等操作,使开发人员只需聚焦于用C语言开发要注入的内核代码。 BCC

[转帖]Linux性能优化(四)——BCC性能监控工具

http://www.javashuo.com/article/p-cxglhftg-nz.html 时间 2021-01-17 标签 前端 python linux ios git github 正则表达式 编程 api 缓存 栏目 Linux 繁體版 原文 https://blog.51cto.

[转帖]Linux性能优化(四)——BCC性能监控工具

原文 https://blog.51cto.com/9291927/2593705 1、BCC简介 一、BCC简介 BCC是一个Python库,简化了eBPF应用的开发过程,并收集了大量性能分析相关的eBPF应用。BCC为BPF开发提供了不一样的前端支持,包括Python和Lua,实现了map建立、

【转帖】Linux性能优化(四)——BCC性能监控工具

一、BCC简介 1、BCC简介 BCC是一个Python库,简化了eBPF应用的开发过程,并收集了大量性能分析相关的eBPF应用。BCC为BPF开发提供了不同的前端支持,包括Python和Lua,实现了map创建、代码编译、解析、注入等操作,使开发人员只需聚焦于用C语言开发要注入的内核代码。 BCC

[转帖]python 性能优化监控工具_Linux性能优化(四)——BCC性能监控工具

一、BCC简介 1、BCC简介 BCC是一个Python库,简化了eBPF应用的开发过程,并收集了大量性能分析相关的eBPF应用。BCC为BPF开发提供了不同的前端支持,包括Python和Lua,实现了map创建、代码编译、解析、注入等操作,使开发人员只需聚焦于用C语言开发要注入的内核代码。 BCC

[转帖]《Linux性能优化实战》笔记(四)—— CPU 使用率

一、 节拍率与CPU时间 前一篇说到,Linux 作为一个多任务操作系统,将每个 CPU 的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉。 为了维护 CPU 时间,Linux 通过事先定义的节拍率(内核中表示为 HZ),触发时间中断,并使用全局变量 Jif

[转帖]linux性能优化笔记之CPU篇

http://blog.trumandu.top/2019/03/02/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E7%AC%94%E8%AE%B0%E4%B9%8BCPU%E7%AF%87/ cpu优化用到的命令 mpstat进程相关统计工具,cpu/io

[转帖]Linux性能优化实战 —— CPU

https://www.jianshu.com/p/2b6658ad59b3 Linux性能分析概要 1. 性能指标 linux性能指标.png 随着应用负载的增加,系统资源的使用也会升高,甚至达到极限。而性能问题的本质,就是系统资源已经达到瓶颈,但请求的处理却还不够快,无法支撑更多的请求。性能分析

[转帖]Linux性能优化(三)——sysstat性能监控工具

http://www.javashuo.com/article/p-dzujtrcz-oa.html 1、sysstat简介 一、sysstat简介 sysstat提供了Linux性能监控工具集,包括sar、sadf、mpstat、iostat、pidstat等,用于监控Linux系统性能和使用状况

[转帖]Linux性能优化(五)——性能监控工具

原文 https://blog.51cto.com/9291927/2594065 1、性能分析工具简介 Brendan Gregg是算机性能设计、分析和调优专家,编写开源大量性能测试工具。http://www.brendangregg.comnode 一、性能分析工具 二、性能观测工具 三、性能测