You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu20.04下如何使用BPF过滤其他应用现有通信的以太网帧

解答

结论先说:完全可以,Ubuntu 20.04 自带的5.4版本原生内核就支持相关能力,不需要升级内核、不需要修改gstreamer源码,有两种成熟落地方案,都能实现在内核层丢包、不让冗余RTP帧送到用户态gstreamer进程的效果,完全匹配你降低解码负载的需求。


方案一:tc 挂载 BPF 到网卡入站路径(推荐,零侵入)

这个方案不需要对gstreamer进程做任何注入操作,过滤点位于网卡收到数据包之后、进入内核协议栈之前,丢包开销最低,配置最简单。

  • 第一步:安装依赖组件
apt update && apt install -y iproute2 linux-tools-common linux-tools-$(uname -r) clang llvm
  • 第二步:编写BPF过滤程序
    核心逻辑为:解析入站数据包的以太网头→IP头→UDP头→RTP头,匹配目标端口为你配置的各路摄像头收流端口(比如示例里的5550,以及其他几路对应的端口),按照你离线测试验证过的RTP序号间隔规则执行丢包,其余数据包直接放行。因为你的摄像头输出全是I帧,不需要做帧类型解析、不需要考虑帧间参考,等间隔丢包不会出现花屏,BPF逻辑可以写得非常轻量。
  • 第三步:挂载BPF规则
    编译BPF程序为目标文件后,先给你连接摄像头对应的物理网卡添加clsact队列规则(以下示例里网卡名为enp0s3,替换成你实际的网卡名即可):
tc qdisc add dev enp0s3 clsact

再将编译好的BPF程序挂载到网卡入站方向:

tc filter add dev enp0s3 ingress bpf obj rtp_drop.o sec classifier direct-action

这个方案的额外优势是可以通过BPF map动态调整丢包间隔,不需要重新加载程序,比如你需要临时调整保留帧率时,直接向map写入新的参数即可,全程不中断视频流。


方案二:BPF套接字过滤器注入到gstreamer现有套接字(精确匹配进程)

如果你需要保证过滤规则只作用于gstreamer进程的流量,完全不影响同端口的其他潜在流量,可以选择这个方案,过滤点位于UDP层将数据包放入套接字接收队列之前,同样不会把待丢弃的包送到用户态。
操作流程:

  • 第一步:定位目标套接字
    先正常启动gstreamer拉流,通过以下命令找到gstreamer进程的PID,以及对应收流端口的套接字fd:
# 找到gstreamer进程PID
pidof gst-launch-1.0
# 找到对应端口的套接字inode,再从/proc/<PID>/fd目录下匹配到对应的fd号
ss -ulnp | grep gst-launch-1.0
  • 第二步:挂载过滤器
    编写简单的BPF加载器,通过pidfd_open获取目标进程的套接字fd句柄,调用setsockopt传入SO_ATTACH_BPF参数,将你写好的RTP丢包BPF程序挂载到对应套接字上即可。
    这个方案的性能和方案一的差异对你5路30FPS的视频流场景完全可以忽略,只是配置步骤稍多。

注意事项

注意:传统libpcap使用的BPF机制只能获取数据包副本、无法干预原数据包的投递路径,不要用libpcap实现这个需求,达不到内核丢包降低负载的效果。

  • 规则生效后可以通过bpftool prog show查看BPF程序的处理、丢包计数,也可以通过top观察gstreamer的CPU占用,和你离线重放测试的效果一致。
  • 如果要清除tc上挂载的BPF规则,执行tc qdisc del dev enp0s3 clsact即可恢复正常流量。

内容的提问来源于stack exchange,提问作者Tik0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:27:19