CPU 在我使用 BPF 过滤器时使用 python 脚本
CPU utilization of python script when I used BPF filters
我从 here 获得代码。
from binascii import hexlify
from ctypes import create_string_buffer, addressof
from socket import socket, AF_PACKET, SOCK_RAW, SOL_SOCKET
from struct import pack, unpack
sniff_interval=120
# A subset of Berkeley Packet Filter constants and macros, as defined in
# linux/filter.h.
# Instruction classes
BPF_LD = 0x00
BPF_JMP = 0x05
BPF_RET = 0x06
# ld/ldx fields
BPF_H = 0x08
BPF_B = 0x10
BPF_ABS = 0x20
# alu/jmp fields
BPF_JEQ = 0x10
BPF_K = 0x00
def bpf_jump(code, k, jt, jf):
return pack('HBBI', code, jt, jf, k)
def bpf_stmt(code, k):
return bpf_jump(code, k, 0, 0)
# Ordering of the filters is backwards of what would be intuitive for
# performance reasons: the check that is most likely to fail is first.
filters_list = [
# Must have dst port 67. Load (BPF_LD) a half word value (BPF_H) in
# ethernet frame at absolute byte offset 36 (BPF_ABS). If value is equal to
# 67 then do not jump, else jump 5 statements.
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 36),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 5201, 0, 5),
# Must be UDP (check protocol field at byte offset 23)
bpf_stmt(BPF_LD | BPF_B | BPF_ABS, 23),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 0, 3),
# Must be IPv4 (check ethertype field at byte offset 12)
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 12),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x0800, 0, 1),
bpf_stmt(BPF_RET | BPF_K, 0x0fffffff), # pass
bpf_stmt(BPF_RET | BPF_K, 0), # reject
]
# Create filters struct and fprog struct to be used by SO_ATTACH_FILTER, as
# defined in linux/filter.h.
filters = ''.join(filters_list)
b = create_string_buffer(filters)
mem_addr_of_filters = addressof(b)
fprog = pack('HL', len(filters_list), mem_addr_of_filters)
# As defined in asm/socket.h
SO_ATTACH_FILTER = 26
# Create listening socket with filters
s = socket(AF_PACKET, SOCK_RAW, 0x0800)
s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, fprog)
s.bind(('eth0', 0x0800))
while True:
data, addr = s.recvfrom(65565)
#print "*****"
print 'got data from', addr, ':', hexlify(data) #Have to print data, then only the CPU is 2%
我正在使用 iperf3
进行测试,通过以太网电缆生成从另一台笔记本电脑到我的笔记本电脑的流量。服务器(我的笔记本电脑)在 5021 上列出,客户端(另一台笔记本电脑)发送数据。
- 如果我评论行
print 'got data from', addr, ':',
hexlify(data)
,运行脚本,CPU脚本的使用
在存在 100MB 流量时上升 30%、40%。
- 如果我再次取消注释行
print 'got data from', addr, ':',
hexlify(data)
和运行,CPU在存在的情况下下降到2%
同样的流量。我入住了
htop
所以,这里发生了什么?
我敢打赌 hexlify()
,或者很可能是 print
(因为它必须与 STDOUT 同步)正在为您的主线程提供急需的休息时间和喘息的空间,而不是只是在无限 while
循环
中敲击套接字读数
尝试添加 time.sleep(0.05)
(当然首先导入 time
)而不是打印语句并再次检查 CPU 用法。
我从 here 获得代码。
from binascii import hexlify
from ctypes import create_string_buffer, addressof
from socket import socket, AF_PACKET, SOCK_RAW, SOL_SOCKET
from struct import pack, unpack
sniff_interval=120
# A subset of Berkeley Packet Filter constants and macros, as defined in
# linux/filter.h.
# Instruction classes
BPF_LD = 0x00
BPF_JMP = 0x05
BPF_RET = 0x06
# ld/ldx fields
BPF_H = 0x08
BPF_B = 0x10
BPF_ABS = 0x20
# alu/jmp fields
BPF_JEQ = 0x10
BPF_K = 0x00
def bpf_jump(code, k, jt, jf):
return pack('HBBI', code, jt, jf, k)
def bpf_stmt(code, k):
return bpf_jump(code, k, 0, 0)
# Ordering of the filters is backwards of what would be intuitive for
# performance reasons: the check that is most likely to fail is first.
filters_list = [
# Must have dst port 67. Load (BPF_LD) a half word value (BPF_H) in
# ethernet frame at absolute byte offset 36 (BPF_ABS). If value is equal to
# 67 then do not jump, else jump 5 statements.
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 36),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 5201, 0, 5),
# Must be UDP (check protocol field at byte offset 23)
bpf_stmt(BPF_LD | BPF_B | BPF_ABS, 23),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 0, 3),
# Must be IPv4 (check ethertype field at byte offset 12)
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 12),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x0800, 0, 1),
bpf_stmt(BPF_RET | BPF_K, 0x0fffffff), # pass
bpf_stmt(BPF_RET | BPF_K, 0), # reject
]
# Create filters struct and fprog struct to be used by SO_ATTACH_FILTER, as
# defined in linux/filter.h.
filters = ''.join(filters_list)
b = create_string_buffer(filters)
mem_addr_of_filters = addressof(b)
fprog = pack('HL', len(filters_list), mem_addr_of_filters)
# As defined in asm/socket.h
SO_ATTACH_FILTER = 26
# Create listening socket with filters
s = socket(AF_PACKET, SOCK_RAW, 0x0800)
s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, fprog)
s.bind(('eth0', 0x0800))
while True:
data, addr = s.recvfrom(65565)
#print "*****"
print 'got data from', addr, ':', hexlify(data) #Have to print data, then only the CPU is 2%
我正在使用 iperf3
进行测试,通过以太网电缆生成从另一台笔记本电脑到我的笔记本电脑的流量。服务器(我的笔记本电脑)在 5021 上列出,客户端(另一台笔记本电脑)发送数据。
- 如果我评论行
print 'got data from', addr, ':', hexlify(data)
,运行脚本,CPU脚本的使用 在存在 100MB 流量时上升 30%、40%。 - 如果我再次取消注释行
print 'got data from', addr, ':', hexlify(data)
和运行,CPU在存在的情况下下降到2%
同样的流量。我入住了htop
所以,这里发生了什么?
我敢打赌 hexlify()
,或者很可能是 print
(因为它必须与 STDOUT 同步)正在为您的主线程提供急需的休息时间和喘息的空间,而不是只是在无限 while
循环
尝试添加 time.sleep(0.05)
(当然首先导入 time
)而不是打印语句并再次检查 CPU 用法。